pulseIn question

I'm trying to use the pulseIn function to decode a WWV timecode, and I can't seem to get numbers that make sense. I have a separate microcontroller (8051) sending my Arduino a 1Hz signal to simulate constant 1s just to troubleshoot the program, and it's acting extremely oddly.

After a while of completely missitng the mark on pulse timing, after every pulseIn I put a Serial.Print(variable); just to see what it was putting out, and it was always what seemed like a completely random number. In under seconds the pulseIn function was putting out anywhere from 0 to 17,000 into the variables.

The thing that boggles my mind is, the time that it was timing wouldn't even BE 17 seconds, and not once did I send it a pulse that long.

Am I missing something?

Thanks.

Edit: On a side note I did have a post of this nature a week ago but I lost it and just recently figure out how to look at my previous posts. I apologize for a repost, but this issue is at least different, as the code contained in that post did work as expected (aside from pulseIn).

COuld you post the code or the URL for the other discussion thread.

Do you have the GNDs of the two processors connected?


Rob

Here’s the finished code of what I’ve been using. I didn’t connect the GNDs of the two, but even just using a button to 5V with a resistor it gets random numbers. It doesn’t have the various Serial.Prints I added to try to debug, but I had them at various stages.

I’m sending a series of timed pulses to pin 8 (though I’ve tried others in case I burnt the pin out or something), and trying to decode the time code from that. However, like I said, they’re all coming back astronomical numbers for short times. My understanding was that the processor waited while it was timing the pulse, and gave the pulse time in milliseconds, but that’s not what I’ve seen.

// 2011/2/20
#include <LiquidCrystal.h>
#include <Time.h> // initialize library
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  // pins for LCD
int wwvbitarray[41] = {  //  41 bits because first bit is always no signal and the last bunch are useless
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0}; 
int wwvinput = 8;  // This is making wwvinput pin 8
unsigned long wwvpulselength;  // This is for the initial synchronizing stage
unsigned long wwvdbrlength;  // This is used for detecting logic 1s, 0s, and markers
int currentMonth;
int currentHour;
int currentMinutes;
int currentSeconds;
int currentDay;
int currentYear = 2011;



void setup()
{
  pinMode(wwvinput, INPUT); // Same as above, wwvinput is pin 8 and an input
  lcd.begin(16, 2);  // initializing the LCD for the size I have
  lcd.print("Please wait."); // Showing something while the decoder finds the time
  Serial.begin(9600)
}

void loop()
{
if(timeStatus() != timeSet)
  wwvpulselength = pulseIn(wwvinput, HIGH);  // This is detecting the 0 second, which will be 1000 milliseconds of HIGH
      Serial.print(wwvpulselength); //THis is what I added to see what the function was returning
      Serial.print(" ");
      if (wwvpulselength > 950000) //  pulseIn times out at 1 second by default, so 950 is what I used
     { setbits();}
  }
  
else {lcd.setCursor(0, 0);
      lcd.print(month());
      lcd.print("/");
      lcd.print(day());
      lcd.print("/");
      lcd.print(year()); // prints month and day
      lcd.setCursor(0, 1); // Sets cursor to bottom left to continue writing
      lcd.print(hour());
      lcd.print(":");
      lcd.print(minute());
      lcd.print(":");
      lcd.print(second());
}
}

void setbits()  //  This is the decoding function to find the logic states for each bit
{
  for (int i=0; i <= 40; i++){ //  41 bits in the array, so it will write to each one; I might be able to drop a couple and do my decoding then
    wwvdbrlength = pulseIn(wwvinput, HIGH);  // this reads the highs of the dB reduced signal and checks the time against if statements
    Serial.print(wwvdbrlength); //This is what I added to see what the function was returning
    Serial.print(" "); //This is to keep them separated
    if (wwvdbrlength < 300000) // markers are 200ms, so 300 gives some leeway
    { wwvbitarray[i] = 2;}
    else if (300000 < wwvdbrlength && wwvdbrlength < 600000) // 1 is 500ms, so 600
    { wwvbitarray[i] = 1;}
    else if (600000 < wwvdbrlength && wwvdbrlength < 900000) // zero will be 800ms of high signal
    { wwvbitarray[i] = 0;}
    else if ( wwvdbrlength > 900000 ) // If the pulse times out or is greater than it should be, it goes back to finding the sync
    { return; }
  }
 currentMinutes = wwvbitarray[9] * 1 + wwvbitarray[10] * 2 + wwvbitarray[11] * 4 + wwvbitarray[12] * 8 + wwvbitarray[14] * 10 + wwvbitarray[15] * 20 + wwvbitarray[16] * 40;
 currentSeconds = 41;
 currentYear = 2011;
 currentHour = (wwvbitarray[19] * 1) + (wwvbitarray[20] * 2) + (wwvbitarray[21] * 4) + (wwvbitarray[22] * 8) + (wwvbitarray[24] * 10) + (wwvbitarray[25] * 20);
 currentDay = (wwvbitarray[29] * 1) + (wwvbitarray[30] * 2) + (wwvbitarray[31] * 4) + (wwvbitarray[32] * 8) + (wwvbitarray[34] * 10) + (wwvbitarray[35] * 20) + (wwvbitarray[36] * 40) + (wwvbitarray[37] * 80) +(wwvbitarray[39] * 100) + (wwvbitarray[40] * 200);
 if (1 <= currentDay <= 31)
   {currentMonth = 1;
 }
 else if (32 <= currentDay && currentDay <= 59)
   {currentMonth = 2;
    currentDay = currentDay - 31;
  }
 else if (60 <= currentDay && currentDay <= 90)
   {currentMonth = 3;
    currentDay = currentDay - 59;
   }
 else if (91 <= currentDay && currentDay <= 120)
   {currentMonth = 4;
    currentDay = currentDay - 90;
   }
 else if (121 <= currentDay && currentDay <= 151)
   {currentMonth = 5;
   currentDay = currentDay - 120;
   }
 else if (152 <= currentDay && currentDay <= 181)
   {currentMonth = 6;
   currentDay = currentDay - 151;
   }
 else if (182 <= currentDay && currentDay <= 212)
  {currentMonth = 7;
  currentDay = currentDay - 181;
  }
 else if (213 <= currentDay && currentDay <= 243)
  {currentMonth = 8;
  currentDay = currentDay - 212;
  }
 else if (244 <= currentDay && currentDay <= 273)
  {currentMonth = 9;
  currentDay = currentDay - 243;
  }
 else if (274 <= currentDay && currentDay <= 304)
  {currentMonth = 10;
  currentDay = currentDay - 273;
  }
 else if (304 <= currentDay && currentDay <= 334)
  {currentMonth = 11;
  currentDay = currentDay - 304;
  }
 else if (335 <= currentDay && currentDay <= 365)
  {currentMonth = 12;
  currentDay = currentDay - 334;
  }
  
  // The above code is just to decode the date and time from the received signals
 setTime(currentHour, currentMinutes, currentSeconds, currentDay, currentMonth, currentYear);
 // setTime is a function of the time.h, this works ok so far  I think. it's hard to tell without valid bit inputs.
 return;
  }
if (32 <= currentDay <= 59)

I’m pretty sure there’s no way that will work.

if (32 <= currentDay && currentDay <= 59)

I didn’t connect the GNDs of the two,

Then it will be random, connect them to get a reliable interface.

but even just using a button to 5V with a resistor it gets random numbers.

Is the button debounced. How do you get regular intervals?


Rob

Graynomad:

if (32 <= currentDay && currentDay <= 59)

Thanks, had no idea that would be an issue.

Graynomad:

I didn’t connect the GNDs of the two,

Then it will be random, connect them to get a reliable interface.

but even just using a button to 5V with a resistor it gets random numbers.

Is the button debounced. How do you get regular intervals?


Rob

Well my understanding from the pulseIn function is that it will wait for the pulse (timing out after 1000ms), then when it goes high, it will count until it goes back low, then return the number that it counted. To me this implies that the time that it says has passed has to have passed between the two edges. If I’m wrong there, that could be the root of the issue.

If that’s what it does, though, I’m not really concerned about debouncing the button or regular intervals, I’m really concerned about why I’m getting anywhere from 0ms to 17000ms returned from the function, within less than a second.

You're right about how pulseIn() works.

I'm really concerned about why I'm getting anywhere from 0ms to 17000ms returned from the function, within less than a second.

From the button or the other processor?


Rob

Graynomad: You're right about how pulseIn() works.

I'm really concerned about why I'm getting anywhere from 0ms to 17000ms returned from the function, within less than a second.

From the button or the other processor?


Rob

Sorry I didn't clarify that. I added Serial.print(wwvpulselength) and Serial.print(wwvdbrlength), to the code after each pulseIn as well as Serial.being(9600) to try to figure out what was going on. I'll add that to the above code. I even did the pulseIn example program on the pulseIn page (http://www.arduino.cc/en/Reference/PulseIn) hoping maybe it was something in my code, but no matter what the numbers it returned were nonsense. It would return 12000ms, 13000ms, etc. and it would return them within milliseconds of eachother, rather than the 12 seconds the returns imply.

Also, in specific answer to your question, both do the same thing.

I can't explain the above but there's no point even looking until we know there's a reliable and stable pulse input.

What are you using now for the pulse input?


Rob

I connected the grounds together on the two microcontrollers and I’m still getting wildly varying numbers. They seem to stay relatively close (they don’t normally jump more than 1000ms at a time), but they’re still much much higher than the time it takes to return the value (over 10k milliseconds and the values are returned in less than a second).

The pulses are approximately 500ms. My understanding is that I should get a bunch of (approximately) 500 returns from the function. I could understand 300-800, if it was consistent in that ballpark I would work around it. The numbers I’m getting though are complete nonsense and I don’t know why.

The part of the loop:

wwvpulselength = pulseIn(wwvinput, HIGH);
if (wwvpulselength > 950)
{ setbits();}

immediately goes to the function because any input whatsoever spikes the value of the pulseIn function to 8000ms at the least.

Also, thanks a lot for the help so far, I really appreciate it, for what it’s worth.

I'd write a short test program, get rid of everything and just have

loop () { Serial.print (pulseIn(8, HIGH)); }


Rob

Look at the manual for "pulsein()". It returns MICROseconds, not MILLIseconds.

17000 microseconds is 17 milliseconds is 0.017 seconds.

johnwasser: Look at the manual for "pulsein()". It returns MICROseconds, not MILLIseconds.

17000 microseconds is 17 milliseconds is 0.017 seconds.

I don't know how I missed that. I'm going to check again with a 555, I think my 8051 is acting up. Thanks a lot for alleviating a huge headache, though. I'm really sorry to waste your time on something so simple Graynomad.

He he, gotcha (and me) :)

Doesn't explain the variations though, see how is goes when you have a reliable pulse train.


Rob

Well, stripped down the program to just be pulseIn and serial prints and sent it pulses with a 555, and while it wasn't perfect, I think the variation was because I was pressing it during the pulse count, so it was catching the end of the pulses. When it caught the entire pulse, it seemed to be correct.

Thanks a lot guys, I changed my code to reflect the changes.

Sorry for the double post, but I have found a new, weird issue. After testing the pulseIn function extensively on my arduino, I've found two things.

1) The timeout field doesn't work. I can put anywhere from 1 to 1000000, and the timeout will still be the same.

2) The counting stops at 200,000 microseconds. Anything above that, and it returns zero consistently. However, if it was below 200,000 microseconds it was spot on. I had a function generator with a square wave 0-5V and the pulseIn function worked down to 3 microseconds. The high level (200,000 mentioned earlier) seemed heavily dependent on what I put in the timeout field, though. While timeout had no effect on the actual timeout, it seemed that if I entered 1000 into that field, it would only get up to about 60,000 microseconds. Once I increased timeout to 10,000,000, I was able to get up to 200,000 microseconds. 10,000,000 was the only number that had that sort of effect, though.

I really can't for the life of me figure out what's going on with it, and it's the basis of the program. Is it possible something's wrong with my arduino itself? I'm honestly dumbfounded. All delay() functions and those sorts of things work perfectly that I've seen, and I can run an LCD perfectly (which I think would be heavily dependent on timing from my short time with assembly language).

I can put anywhere from 1 to 1000000

The compiler treats constant values as ints, unless explicitly told otherwise. For values above 32767, are you explicitly telling the compiler that the constant is not to be treated as an int? 50000UL tells the compiler that 50000 is to be treated as an unsigned long, instead of an int.

If the compiler is treating your constant as an int, 50000 will be a negative number, and negative timeouts generally do not work well.

Yea I was assigning it as unsigned long. I didn't know I could do #UL, though, thanks!

Even 10,000,000UL yields a timeout of less than a second, and I still can't get anything to come out with a 1Hz signal. Using digitalread, I get high when it's high and low when it's low so the pin is seeing the changes, pulsein just doesn't work above 200,000 microseconds.

The manual says it should work for pulses from 10 microseconds to 3 minutes (=180 seconds =180 million microseconds). Don't know why it can't go up to the unsigned long limit of nearly 4.3 billion.

Hope you didn't write your unsigned long constants with commas:

pulseIn(7, HIGH, 10,000,000UL) -> pulseIn(7, HIGH, 10, 0, 0UL)

No sir I was just doing that to keep the zeros apart in my head, the exact thing I wrote was duration = pulseIn(pin, HIGH, 10000000UL)

or

duration = pulseIn(pin, LOW, timeout)

where timeout was unsigned long timeout = 10000000

just in case.