Arduino IR sensor - low range - c

I'm programming Arduino. I have a problem with the IR sensor. It only detects this ball (equiped with IR LEDS) in range of 0,5m and I would need at least 2m. This is the ball:
"http://drgraeme.net/drgraeme-free-nxt-g-tutorials/Ch108/SoccerGenIINXTG/Soccer%20Ball/HiTechnicRCJ05V2.jpg"
and this is my arduino code:
// digital pin 2 has a pushbutton attached to it. Give it a name:
int IR = 2;
int i = 0;
int ii = 0;
int led = 0;
void setup()
{
Serial.begin(9600);
pinMode(IR, INPUT_PULLUP);
pinMode(led, OUTPUT);
}
void loop() {
i = 0;
ii = 0;
do
{
i = i + 1;
int STANJE1 = digitalRead(IR);
if(STANJE1 < 1)
{
ii = ii + 1;
}
}while(i<1000);
if(ii > 1)
{Serial.println("IS");}
else{Serial.println("IS NOT");}
}
IR sensor is 38kHZ and the balls LEDs are 40kHZ, but I found a program that allowed me to detect the ball 10m away from sensor, but It was ment for something else, and I didn't understand it, so that is not the problem.
This is the code that works further (That's because it doesn't use "DigitalRead()")
/* Raw IR decoder sketch!
This sketch/program uses the Arduno and a PNA4602 to
decode IR received. This can be used to make a IR receiver
(by looking for a particular code)
or transmitter (by pulsing an IR LED at ~38KHz for the
durations detected
Code is public domain, check out www.ladyada.net and adafruit.com
for more tutorials!
*/
// We need to use the 'raw' pin reading methods
// because timing is very important here and the digitalRead()
// procedure is slower!
//uint8_t IRpin = 2;
// Digital pin #2 is the same as Pin D2 see
// http://arduino.cc/en/Hacking/PinMapping168 for the 'raw' pin mapping
#define IRpin_PIN PIND
#define IRpin 2
// the maximum pulse we'll listen for - 65 milliseconds is a long time
#define MAXPULSE 65000
// what our timing resolution should be, larger is better
// as its more 'precise' - but too large and you wont get
// accurate timing
#define RESOLUTION 20
// we will store up to 100 pulse pairs (this is -a lot-)
uint16_t pulses[100][2]; // pair is high and low pulse
uint8_t currentpulse = 0; // index for pulses we're storing
void setup(void) {
Serial.begin(9600);
Serial.println("Ready to decode IR!");
}
void loop(void) {
uint16_t highpulse, lowpulse; // temporary storage timing
highpulse = lowpulse = 0; // start out with no pulse length
// while (digitalRead(IRpin)) { // this is too slow!
while (IRpin_PIN & (1 << IRpin)) {
// pin is still HIGH
// count off another few microseconds
highpulse++;
delayMicroseconds(RESOLUTION);
// If the pulse is too long, we 'timed out' - either nothing
// was received or the code is finished, so print what
// we've grabbed so far, and then reset
if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
printpulses();
currentpulse=0;
return;
}
}
// we didn't time out so lets stash the reading
pulses[currentpulse][0] = highpulse;
// same as above
while (! (IRpin_PIN & _BV(IRpin))) {
// pin is still LOW
lowpulse++;
delayMicroseconds(RESOLUTION);
if ((lowpulse >= MAXPULSE) && (currentpulse != 0)) {
printpulses();
currentpulse=0;
return;
}
}
pulses[currentpulse][1] = lowpulse;
// we read one high-low pulse successfully, continue!
currentpulse++;
}
void printpulses(void) {
Serial.println("\n\r\n\rReceived: \n\rOFF \tON");
for (uint8_t i = 0; i < currentpulse; i++) {
Serial.print(pulses[i][0] * RESOLUTION, DEC);
Serial.print(" usec, ");
Serial.print(pulses[i][1] * RESOLUTION, DEC);
Serial.println(" usec");
}
}

Related

dsPIC33 ADC1 gives incorrect converted values

Good morning,
I am using the ADC1 of a dsPIC33EP512GM604 and getting incorrect converted values.
To check this I made a cycle of 10 consecutive sampling/conversions.
The first value is always quite different from the rest of them, but it is the nearest to the "right" value.
Here is the relevant code:
/* Setup ADC1 for measuring R */
ANSELBbits.ANSB3 = 1; //ensure AN5 is analog
TRISBbits.TRISB3 = 1; //ensure AN5 is input
AD1CON1 = 0;
AD1CON1bits.ADSIDL = 1;
AD1CON1bits.AD12B = 1;
AD1CON1bits.SSRC = 7;
AD1CON2 = 0;
AD1CON2bits.VCFG = 0b001;
AD1CON2bits.SMPI = 0;
AD1CON3=0;
AD1CON3bits.SAMC = 0b11111;
AD1CON3bits.ADCS = 0;
AD1CON4 = 0; // no dma
AD1CHS0bits.CH0NA = 0;
AD1CHS0bits.CH0SA = 5;
IFS0bits.AD1IF = 0; // Clear the A/D interrupt flag bit
IEC0bits.AD1IE = 0; // Do Not Enable A/D interrupt
/* Read voltage value */
AD1CON1bits.ADON = 1; // Enable the A/D converter
__delay_us(25);
for (N=0; N<10; N++) {
AD1CON1bits.SAMP = 1;
__delay_us(5); // Wait for sampling time (min 3 TAD)
AD1CON1bits.SAMP = 0; // Start the conversion
while (!AD1CON1bits.DONE); // wait for conversion to finish
res[N] = (double) ADC1BUF0;
/* --- just for test ---*/
sprintf(deb,"ADC1BUF0 = %.0f\r\n", res[N]);
WriteStringUART1(deb);
/* ---- end of test ----*/
And here the results, for a certain fixed input voltage corresponding to a value of 215:
ADC1BUF0 = 222
ADC1BUF0 = 301
ADC1BUF0 = 296
ADC1BUF0 = 295
ADC1BUF0 = 295
ADC1BUF0 = 296
ADC1BUF0 = 296
ADC1BUF0 = 296
ADC1BUF0 = 296
ADC1BUF0 = 295
The first value 222 is acceptable close to the expected 215, to my purposes, the other values not.
What am I doing wrong?
I've used dsPIC33FJ64MC802 and was able to use the ADC.
I don't have much idea why the readings are that way. The code below worked for me. However, I can't say for sure that it will work properly for you.
void initADC() {
AD1CON1 = 0;
AD1CON1bits.AD12B = 1;
AD1CON2 = 0;
AD1CON3 = 0;
AD1CON3bits.ADCS = 2;
AD1CHS0 = 0;
AD1CON1bits.ADON = 1;
delayMs(1);
}
int readADC(char pin, unsigned samplingCycles) {
AD1CHS0bits.CH0SA = pin;
AD1CON1bits.SAMP = 1;
__delay32(samplingCycles);
AD1CON1bits.SAMP = 0;
while(!AD1CON1bits.DONE);
return ADC1BUF0;
}
Thanks to everybody for the contributions.
I finally got the trick. I then post the answer to my own question in case it may help someone.
Here is the trick:
The dsPIC can use different VrefH for the ADC1, ie. internal Vdd or external on PIN.
I used a HW that takes 2.5V external Vref on a dsPIC pin to be used as VrefH, and set the ADC accordingly.
The problem is that the dsPIC specs state that VrefH external should be greater than 2.7 V. So 2.5 was not sufficient to make it work well. That's foolishly it!
Here is ADC code example which I made before and connection diagram for AN2 with dsPIC33EV.
#define FCY 3685000UL // __delay_ms() and __delay_us() depend on FCY.
#include <xc.h> // p33EV256GM102.h
#include <libpic30.h>
void pins_init()
{
// ANSELx has a default value of 0xFFFF
// 1 = Pin is configured as an analog input
// 0 = Pin is configured as a digital I/O pin
ANSELA = ANSELB = 0x0000; // In most cases, it is better to initially set them to 0.
}
unsigned short adc1_raw = 0;
void adc1_init()
{
// See 70621c.pdf, Example 16-3: Code Sequence to Set Up ADC Inputs
ANSELBbits.ANSB0 = 1; // pin 4 - AN2/RPI32/RB0. 1 = Pin is configured as an analog input
AD1CHS0bits.CH0SA = 2; // Channel 0 positive input is AN2. See AD1CON2bits.ALTS
AD1CHS0bits.CH0NA = 0; // 0 = Channel 0 negative input is VREFL
AD1CON1bits.FORM = 0; // 00 = unsigned integer VREFL:0..VREFH:1023
AD1CON1bits.ASAM = 0; // 0 = Sampling begins when SAMP bit is set
AD1CON1bits.AD12B = 0; // 0 = 10-bit, 4-channel ADC operation
AD1CON2bits.VCFG = 0; // AVdd for VREFH and AVss for VREFL
AD1CON2bits.CHPS = 0; // 00 = Converts CH0. Select 1-channel mode.
AD1CON2bits.CSCNA = 0; // 0 = Does not scan inputs
AD1CON2bits.ALTS = 0; // 0 = Always uses channel input selects for Sample MUX A
AD1CON3bits.ADRC = 0; // 0 = clocked from the instruction cycle clock (TCY)
AD1CON3bits.ADCS = 15; // Conversion Clock Select bits. Tad=Tcy*(ADCS+1)=(1/Fcy)*(ADCS+1)
// Tad = (1/3685000)*(15+1) = 4342 ns
// (10-bit) Tconv = 12 * Tad = 52104 ns = 52.1 us.
IFS0bits.AD1IF = 0; // Clear the A/D interrupt flag bit
IEC0bits.AD1IE = 0; // Do Not Enable A/D interrupt
AD1CON1bits.ADON = 1; // turn on ADC
__delay_us(20); // ADC stabilization delay.
}
unsigned short adc1_read()
{
AD1CON1bits.SAMP = 1; // start sampling
__delay_us(100); // Wait for (enough) sampling time
AD1CON1bits.SAMP = 0; // start converting. See AD1CON1bits.ASAM
while (!AD1CON1bits.DONE)
{
; // Wait for the conversion to complete.
// In bare metal programming, most infinite loop issues
// are handled by watchdog reset.
}
return ADC1BUF0;
}
int main(void)
{
pins_init();
adc1_init();
while (1)
{
ClrWdt();
adc1_raw = adc1_read();
}
return 0;
}

Call of function without prototype error message with Delay1TCYx (1) ( C language )

We have a project that were running using C and a PICkit 3. Our issu is that we remain getting the same error message and arent sure whta the issue is. Any help / advice would be great.
void main (void)
{
ANSEL = 0; //turn off all other analog inputs
ANSELH = 0;
ANSELbits.ANS0 = 1; // turn on RA0 analog
ADCON0 = 1; // justify right
ADC_Init(); // Call ADC_Init function
ADC_Convert();
Delay1TCYx(1); //delay 1 x 1 cycles
int reading0 = ADRESL + (ADRESH * 256); //convert result to 10 bits
if (reading0 = 0b1000000011)
{
readingsamples();
}
while(1);
}

Arduino boolean array; 1 true and the rest false

I have a question about arduino considering a setup with 8 leds and an potentiometer. I want to let 1 led light up, which is the led that matches the value returned by the potentiometer, and the rest of the leds should be turned off. Furthermore, when I change the position of the potentiometer, the leds should change accordingly. So far ive got this:
for(int i = 0; i)
{
if (i = draaiKnopStand)
{
status[i] = HIGH;
}
else
{
status[i] = LOW;
}
digitalWrite(draaiKnopStand, status[i]);
}
I'm considering this is Arduino Uno Front
I have no Arduino here in my job. I did this using a simulator. Please try it:
int _potentiometer = 9; // Potentiometer - Analog Pin
int _val = 0;
int _borderLineVal = 0;
int ledPins[] = { 2, 3, 4, 5, 6, 7 }; // an array of pin numbers to which LEDs are attached
int pinCount = 6; // the number of pins (i.e. the length of the array)
void setup() {
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
pinMode(ledPins[thisPin], OUTPUT);
}
}
void loop() {
_val = analogRead(_potentiometer); //reading the Potentiometer value interval: 0 - 1023
_borderLineVal = (int)(1023 / pinCount);
Serial.println(_val);
// turn all leds off
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
digitalWrite(ledPins[thisPin], LOW);
}
// turn the select led on
if(_val > 0){
_pinHigh = (int)(1023 / _borderLineVal);
digitalWrite(ledPins[_pinHigh], HIGH); // turn the pin on
}
}

Identified amplitude in secret knock project

I'm doing project like this http://grathio.com/2013/11/new-old-project-secret-knock-drawer-lock/ The project only process time interval between knock, and I try to add amplitude as input, if I just use the code from the link above it works fine but I want to add amplitude (loud and soft knock) as input too. But my code still have problem, it can't recognise knock and the LED acting weird. I need to recognise knock time interval and knock amplitude. Comment 'This is what I add' is the code that I add myself, but the code doesn't work. Could anyone tell me what is wrong with my code?
Below is the code:
#include <EEPROM.h>
const byte eepromValid = 123; // If the first byte in eeprom is this then the data is valid.
/*Pin definitions*/
const int programButton = 0; // Record A New Knock button.
const int ledPin = 1; // The built in LED
const int knockSensor = 1; // (Analog 1) for using the piezo as an input device. (aka knock sensor)
const int audioOut = 2; // (Digial 2) for using the peizo as an output device. (Thing that goes beep.)
const int lockPin = 3; // The pin that activates the solenoid lock.
/*Tuning constants. Changing the values below changes the behavior of the device.*/
int threshold = 3; // Minimum signal from the piezo to register as a knock. Higher = less sensitive. Typical values 1 - 10
const int rejectValue = 25; // If an individual knock is off by this percentage of a knock we don't unlock. Typical values 10-30
const int averageRejectValue = 15; // If the average timing of all the knocks is off by this percent we don't unlock. Typical values 5-20
const int knockFadeTime = 150; // Milliseconds we allow a knock to fade before we listen for another one. (Debounce timer.)
const int lockOperateTime = 2500; // Milliseconds that we operate the lock solenoid latch before releasing it.
const int maximumKnocks = 20; // Maximum number of knocks to listen for.
const int maximumAmp = 20; // This is what i add
const int ampLoud = 10; // This is what i add
const int ampSoft = 20; // This is what i add
const int knockComplete = 1200; // Longest time to wait for a knock before we assume that it's finished. (milliseconds)
byte secretCode[maximumKnocks] = {50, 25, 25, 50, 100, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Initial setup: "Shave and a Hair Cut, two bits."
byte secretAmp[maximumAmp] = {10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // This is what i add
int knockReadings[maximumKnocks]; // When someone knocks this array fills with the delays between knocks.
int ampReadings[maximumAmp]; // This is what i add
int knockSensorValue = 0; // Last reading of the knock sensor.
int amp = 0; // This is what i add
boolean programModeActive = false; // True if we're trying to program a new knock.
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(lockPin, OUTPUT);
readSecretKnock(); // Load the secret knock (if any) from EEPROM.
doorUnlock(500); // Unlock the door for a bit when we power up. For system check and to allow a way in if the key is forgotten.
delay(500); // This delay is here because the solenoid lock returning to place can otherwise trigger and inadvertent knock.
}
void loop() {
// Listen for any knock at all.
knockSensorValue = analogRead(knockSensor);
if (digitalRead(programButton) == HIGH){ // is the program button pressed?
delay(100); // Cheap debounce.
if (digitalRead(programButton) == HIGH){
if (programModeActive == false){ // If we're not in programming mode, turn it on.
programModeActive = true; // Remember we're in programming mode.
digitalWrite(ledPin, HIGH); // Turn on the red light too so the user knows we're programming.
chirp(500, 1500); // And play a tone in case the user can't see the LED.
chirp(500, 1000);
} else { // If we are in programing mode, turn it off.
programModeActive = false;
digitalWrite(ledPin, LOW);
chirp(500, 1000); // Turn off the programming LED and play a sad note.
chirp(500, 1500);
delay(500);
}
while (digitalRead(programButton) == HIGH){
delay(10); // Hang around until the button is released.
}
}
delay(250); // Another cheap debounce. Longer because releasing the button can sometimes be sensed as a knock.
}
if (knockSensorValue >= threshold){
if (programModeActive == true){ // Blink the LED when we sense a knock.
digitalWrite(ledPin, LOW);
} else {
digitalWrite(ledPin, HIGH);
}
knockDelay();
if (programModeActive == true){ // Un-blink the LED.
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
listenToSecretKnock(); // We have our first knock. Go and see what other knocks are in store...
}
}
// Records the timing of knocks.
void listenToSecretKnock(){
int i = 0;
int j = 0;
// First reset the listening array.
for (i=0; i < maximumKnocks; i++){
knockReadings[i] = 0;
}
for (j=0; j < maximumAmp; j++){ // This is what i add
ampReadings[j] = 0;
}
int currentKnockNumber = 0; // Position counter for the array.
int currentAmpNumber = 0;
int startTime = millis(); // Reference for when this knock started.
int now = millis();
do { // Listen for the next knock or wait for it to timeout.
knockSensorValue = analogRead(knockSensor);
//===========================================================================================================
if(knockSensorValue >=3 && knockSensorValue <=75){ // This is what i add
amp = ampSoft; // This is what i add
}
if(knockSensorValue >=76){ // This is what i add
amp = ampLoud; // This is what i add
}
ampReadings[currentAmpNumber] = amp; // This is what i add
currentAmpNumber++; // This is what i add
//===========================================================================================================
if (knockSensorValue >= threshold){ // Here's another knock. Save the time between knocks.
now=millis();
knockReadings[currentKnockNumber] = now - startTime;
currentKnockNumber ++;
startTime = now;
if (programModeActive==true){ // Blink the LED when we sense a knock.
digitalWrite(ledPin, LOW);
} else {
digitalWrite(ledPin, HIGH);
}
knockDelay();
if (programModeActive == true){ // Un-blink the LED.
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
}
now = millis();
// Stop listening if there are too many knocks or there is too much time between knocks.
} while ((now-startTime < knockComplete) && (currentKnockNumber < maximumKnocks));
//we've got our knock recorded, lets see if it's valid
if (programModeActive == false){ // Only do this if we're not recording a new knock.
if (validateKnock() == true){
doorUnlock(lockOperateTime);
} else {
// knock is invalid. Blink the LED as a warning to others.
for (i=0; i < 4; i++){
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(ledPin, LOW);
delay(50);
}
}
} else { // If we're in programming mode we still validate the lock because it makes some numbers we need, we just don't do anything with the return.
validateKnock();
}
}
// Unlocks the door.
void doorUnlock(int delayTime){
digitalWrite(ledPin, HIGH);
digitalWrite(lockPin, HIGH);
delay(delayTime);
digitalWrite(lockPin, LOW);
digitalWrite(ledPin, LOW);
delay(500); // This delay is here because releasing the latch can cause a vibration that will be sensed as a knock.
}
// Checks to see if our knock matches the secret.
// Returns true if it's a good knock, false if it's not.
boolean validateKnock(){
int i = 0;
int currentKnockCount = 0;
int secretKnockCount = 0;
int currentAmpCount = 0; // This is what i add
int secretAmpCount = 0; // This is what i add
int maxKnockInterval = 0; // We use this later to normalize the times.
for (i=0;i<maximumKnocks;i++){
if (knockReadings[i] > 0){
currentKnockCount++;
}
if (secretCode[i] > 0){
secretKnockCount++;
}
if (ampReadings[i] > 0){ // This is what i add
currentAmpCount++; // This is what i add
}
if (secretAmp[i] > 0){ // This is what i add
secretAmpCount++; // This is what i add
}
if (knockReadings[i] > maxKnockInterval){ // Collect normalization data while we're looping.
maxKnockInterval = knockReadings[i];
}
}
// If we're recording a new knock, save the info and get out of here.
if (programModeActive == true){
for (i=0; i < maximumKnocks; i++){ // Normalize the time between knocks. (the longest time = 100)
secretCode[i] = map(knockReadings[i], 0, maxKnockInterval, 0, 100);
}
for (int j = 0; j < maximumAmp; j++){
secretAmp[j] = ampReadings[j];
}
saveSecretKnock(); // save the result to EEPROM
programModeActive = false;
playbackKnock(maxKnockInterval);
return false;
}
if (currentKnockCount != secretKnockCount && currentAmpCount != secretAmpCount){ // Easiest check first. If the number of knocks is wrong, don't unlock. // This is what i add
return false;
}
/* Now we compare the relative intervals of our knocks, not the absolute time between them.
(ie: if you do the same pattern slow or fast it should still open the door.)
This makes it less picky, which while making it less secure can also make it
less of a pain to use if you're tempo is a little slow or fast.
*/
int totaltimeDifferences = 0;
int timeDiff = 0;
for (i=0; i < maximumKnocks; i++){ // Normalize the times
knockReadings[i]= map(knockReadings[i], 0, maxKnockInterval, 0, 100);
timeDiff = abs(knockReadings[i] - secretCode[i]);
if (timeDiff > rejectValue){ // Individual value too far out of whack. No access for this knock!
return false;
}
totaltimeDifferences += timeDiff;
}
// It can also fail if the whole thing is too inaccurate.
if (totaltimeDifferences / secretKnockCount > averageRejectValue){
return false;
}
return true;
}
// reads the secret knock from EEPROM. (if any.)
void readSecretKnock(){
byte reading;
int i;
int j;
reading = EEPROM.read(0);
if (reading == eepromValid){ // only read EEPROM if the signature byte is correct.
for (int i=0; i < maximumKnocks ;i++){
secretCode[i] = EEPROM.read(i+1);
}
for (int j=0; j < maximumAmp ;j++){ // This is what i add
secretAmp[j] = EEPROM.read(j+1); // This is what i add
}
}
}
//saves a new pattern too eeprom
void saveSecretKnock(){
EEPROM.write(0, 0); // clear out the signature. That way we know if we didn't finish the write successfully.
for (int i=0; i < maximumKnocks; i++){
EEPROM.write(i+1, secretCode[i]);
EEPROM.write(i+1, secretAmp[i]); // This is what i add
}
EEPROM.write(0, eepromValid); // all good. Write the signature so we'll know it's all good.
}
// Plays back the pattern of the knock in blinks and beeps
void playbackKnock(int maxKnockInterval){
digitalWrite(ledPin, LOW);
delay(1000);
digitalWrite(ledPin, HIGH);
chirp(200, 1800);
for (int i = 0; i < maximumKnocks ; i++){
digitalWrite(ledPin, LOW);
// only turn it on if there's a delay
if (secretCode[i] > 0){
delay(map(secretCode[i], 0, 100, 0, maxKnockInterval)); // Expand the time back out to what it was. Roughly.
digitalWrite(ledPin, HIGH);
chirp(200, 1800);
}
}
digitalWrite(ledPin, LOW);
}
// Deals with the knock delay thingy.
void knockDelay(){
int itterations = (knockFadeTime / 20); // Wait for the peak to dissipate before listening to next one.
for (int i=0; i < itterations; i++){
delay(10);
analogRead(knockSensor); // This is done in an attempt to defuse the analog sensor's capacitor that will give false readings on high impedance sensors.
delay(10);
}
}
// Plays a non-musical tone on the piezo.
// playTime = milliseconds to play the tone
// delayTime = time in microseconds between ticks. (smaller=higher pitch tone.)
void chirp(int playTime, int delayTime){
long loopTime = (playTime * 1000L) / delayTime;
pinMode(audioOut, OUTPUT);
for(int i=0; i < loopTime; i++){
digitalWrite(audioOut, HIGH);
delayMicroseconds(delayTime);
digitalWrite(audioOut, LOW);
}
pinMode(audioOut, INPUT);
}
I'm guessing that you are wanting to record the knock pattern and knock volume at the same time. So that a similar pattern with softer or louder knocks will not activate the lock. If this is the case, I would suggest that you make the array mySecretKnock a 2 dimensional array.
Then use two variables to record the analog and digital inputs.
Capture them one after the other in the same control structure.
i.e. If the value of one is high enough to trigger the if statement just record the value of the other one on the next line of code.
Keep in mind that the analog input will be lower if processed after the digital one, so you may have to adjust your threshold numbers

Arduino IDE: Print once inside loop

I am using a LDR to tell me whether there is light or not with an Arduino. My code is pretty simple, but instead of spamming "light light light light" I would like it to say "light" once, and then if the light goes off, for it to say "No light" once.
code edited from "readanalogvoltage":
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);
// print out the value you read:
if (voltage > 1.5)
{
Serial.print("Light");
Serial.println();
delay(5000);
}
if (voltage < 1.5)
{
Serial.print("No Light");
Serial.println();
delay(50);
}
}
Keep a variable that holds the last state:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
int wasLit = 0;
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);
// print out the value you read:
if (!wasLit && voltage > 1.5) {
wasLit = 1;
Serial.print("Light");
Serial.println();
delay(5000);
} else if(wasLit && voltage <= 1.5) {
wasLit = 0;
Serial.print("No Light");
Serial.println();
delay(50);
}
}
This sort of test will benefit from use of hysterisis. Especially if you have flourescent light, there will be some flicker. That will cause the sensor reading to vary such that it may not change from <1.5 to >=1.5 in a clean manner.
boolean bLast = false;
const float vTrip = 1.5;
// you find a good value for this by looking at the noise in readings
// use a scratch program to just read in a loop
// set this value to something much larger than any variation
const float vHyst = 0.1;
float getLight() {
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);
return voltage;
}
void setup() {
// establish the initial state of the light
float v = getLight();
bLast = ( v < (vTrip-vHyst) );
}
void loop() {
float v = getLight();
if( bLast ) {
// light was on
// when looking for decreasing light, test the low limit
if( v < (vTrip-vHyst) ) {
bLast = false;
Serial.print("Dark");
}
}
else {
// light was off
// when looking for increasing light, test the high limit
if( v > (vTrip+vHyst) ) {
bLast = true;
Serial.print("Light");
}
}
}

Resources