Help Debugging Code, pulseIn watching for a square wave.

After much support from this forum i was finally able to come up with a code that does what i need for my project.

Its just a "watchdog" when a 12500hz pulse is present it turns on an led, and when the signal is gone it turns off the led.

The problem i am experiencing, is my led will flicker, or turn off briefly, when it should be solid lit.

The input signal is steady, i can adjust my thresholds all over the place and the blinking still occurs. When the circuit is "off" it does not blink "on" it only blinks off when it should be solidly lit {trigger signal is present}

i have tried various pull ups and pull downs on the input. Ive tried a few different capacitors in various configurations {no method, just plugging things in really}

Ive tried adding delays of various lengths in various spots in the code. with limited success. The part that really gets me is even with these long delays in place, the blink is quicker than the circuit responds to actual input change.

Depending where i put the delays i can make the blink slower {more pronounced} or faster {less noticeable} but i cannot eliminate it.

It seems like the code is overflowing and causing some sort of reset.

or possibly there is noise on the input line that i really don't know how to deal with.

I am using an Arduino Uno r3 for programming and running the code on an ATTINY45 thats imbedded.

int inPin = 3;  // Charge Pump Input Packge Pin 2:
const int ledPin =  2;   // Current Enable {Half} Package Pin 7:
const int led2Pin =  1;  // Current Enable {Full} Package Pin 6:
const int SpinPin =  0;  // Spindle Enable Package Pin 5:
unsigned int duration;  // VCC+ Package Pin 8, GND Package Pin 4:


void setup() {
  pinMode(ledPin, OUTPUT); // initialize the Current Enable pin as an output:
  pinMode(SpinPin, OUTPUT); // initialize the Spindle pin as an output:
  pinMode(inPin, INPUT_PULLUP); // make the pin an input:
}

void loop() {
  duration = pulseIn(inPin, HIGH, 200);
  if(duration >=20)
  {
    digitalWrite(ledPin, HIGH);
   digitalWrite(led2Pin, HIGH); // Enables Current Enable Opto:
   delay(200);
  }
  else{
    digitalWrite(ledPin, LOW);
   digitalWrite(led2Pin, LOW); // turn Current Enable off:
  }
  if (digitalRead(ledPin) == HIGH  && digitalRead(4) == HIGH) // Spindle input from pc
                                                       //Digital 4 is Package Pin 3:
  { 
    digitalWrite(SpinPin, LOW); // Enables Spindle Opto:
  }
  else{
    digitalWrite(SpinPin, HIGH); // turn Spindle off:
  }
}

It doesn't seem to make sense to write a value to the LED pin and then attempt to read the value back from the pin

It may work but you would be better off storing the value you assigned to the pin in a variable and then checking that variable

Awesome!

I whole heartedly expect my approach to make little sense. I'm just sort of cobbling as i go.

What would be a more correct approach to toggling the 2nd pin? use the if duration >20 statement instead?

iirc, even without the 2nd pin code at all, the blink still persists.

will confirm this after dinner.

 duration = pulseIn(inPin, HIGH, 200);
  if(duration >=20)
  {
    digitalWrite(ledPin, HIGH);
   digitalWrite(led2Pin, HIGH); // Enables Current Enable Opto:
   delay(200);
  }
  else{
    digitalWrite(ledPin, LOW);
   digitalWrite(led2Pin, LOW); // turn Current Enable off:
  }

If that code is causing the LED to flicker it MUST be because some of the time duration is below 20 and other times above it

I suggest putting in some Serial.println()s to see what is happening.

I note that your delay() only applies in one side of the IF statement - is that what you intend? Is delay() needed at all?

...R

Ok so heres the confusing part.

pulesin takes a sample over a 1 second period. Lets say i disconnect the signal input wire, if i unplug it and plug it back in quick enough, the led doesn't blink!

The blink seems to come randomly. I have changed the duration all the way down to >0 and >1 which still doesn't eliminate the blink.

I have tried putting the delay in different spots within the code {it didnt originally have the delay at all} i can't say it is necessary just an attempt to get the glitch out.

I will post a quick video of what i have got going.

Kawgomoo:
Ok so heres the confusing part.

pulesin takes a sample over a 1 second period. Lets say i disconnect the signal input wire, if i unplug it and plug it back in quick enough, the led doesn’t blink!

For sure !

What do you mean by “pulseIn() takes a sample over a 1 second period”. There is no time mentioned in your code, apart from a 200 usec timeout.

This sounds to me like random tinkering rather than systematic debugging.

There is no point making a change to either hardware or software unless you first have a theory about what the change will do. Then the change will either confirm or contradict that theory. If it contradicts the theory it gives you more data from which to formulate a new theory and a new test.

Have you an oscilloscope so you can watch the signal as the Arduino is receiving it.
What is producing the 12,500 Hz signal?
Is it a square wave or a sine wave?
What amplitude is it?

Have you another Arduino that could be programmed to produce a 12,500Hz square wave and use that for input and see what happens?

Is this testing taking place on an Uno or an Attiny? I would get it to work on the Uno first.

…R

Kawgomoo: Ok so heres the confusing part.

pulesin takes a sample over a 1 second period. Lets say i disconnect the signal input wire, if i unplug it and plug it back in quick enough, the led doesn't blink!

The blink seems to come randomly. I have changed the duration all the way down to >0 and >1 which still doesn't eliminate the blink.

I have tried putting the delay in different spots within the code {it didnt originally have the delay at all} i can't say it is necessary just an attempt to get the glitch out.

I will post a quick video of what i have got going.

I am not sure if either of these is the cause of your blinking problem, but: 1. The Pulsein() function by default WAITS for 1 second for the pulse to start if no timeout value is set. In your code the timeout is set for 200 so the Pulsein() function will wait for 200 microseconds for a pulse and then return 0. To quote the reference document " timeout (optional): the number of microseconds to wait for the pulse to start; default is one second (unsigned long) " 2. The Pulsein() function returns an unsigned long. You have "duration" defined as unsigned int.

What do you mean by "pulseIn() takes a sample over a 1 second period". There is no time mentioned in your code, apart from a 200 used timeout.

I meant timeout is set at 1000ms by default. i have this set at 200ms right now to make the circuit respond, or turn off faster. leaving it at default does not make it anymore stable.

This sounds to me like random tinkering rather than systematic debugging.

Exactly!

There is no point making a change to either hardware or software unless you first have a theory about what the change will do. Then the change will either confirm or contradict that theory. If it contradicts the theory it gives you more data from which to formulate a new theory and a new test.

Just tinkering, no clue what I'm doing or why. All i know is what i WANT it to do.

Have you an oscilloscope so you can watch the signal as the Arduino is receiving it.

Nope

What is producing the 12,500 Hz signal? Is it a square wave or a sine wave? What amplitude is it?

Laptop computer, signal is generated by mach3 cnc software. i really don't know the specifics at all.

Have you another Arduino that could be programmed to produce a 12,500Hz square wave and use that for input and see what happens?

I have one Arduino uno r3 and 4 attiny45 chips. i can set the arduino to be a tone generator after I've pushed the code onto an attiny. when i serial monitor the signal using pulsein i get a return of 31-40

Is this testing taking place on an Uno or an Attiny? I would get it to work on the Uno first.

Both. same issues on both the Uno and the attiny. the tiny doesn't support serial so i removed that much from the code, when i was doing this on the uno i had serial print in their so i could watch the return in the monitor window. ...R [/quote]

Just tinkering, no clue what I'm doing or why. All i know is what i WANT it to do.

Well let's try to be systematic.

Can you program an Attiny so it produces a 12500Hz square wave and then use the Uno for testing?

FIRST Try this code on your Uno (preferrably with a constant square wave coming from an Attiny, but, otherwise from your Mach 3 device)

void loop() {
   unsigned long duration = pulseIn(inPin, HIGH, 200);
   Serial.println(duration);
   delay(1000);
}

and report your results.

SECOND If you are running Mach3 on your laptop how is the 12500Hz signal getting from the laptop to the Arduino? Is there some hardware connected to the laptop? If so what?

...R

Can you program an Attiny so it produces a 12500Hz square wave and then use the Uno for testing?

I can try. Most arduino libraries don’t carry over to the tiny so well. {if so i could have stuck with freqcount that i was using and id be done!}

FIRST
Try this code on your Uno (preferrably with a constant square wave coming from an Attiny, but, otherwise from your Mach 3 device)

void loop() {

unsigned long duration = pulseIn(inPin, HIGH, 200);
   Serial.println(duration);
   delay(1000);
}




and report your results.

heres how i stuck the code in there, took me a few tries to figure it out. It makes the led blink slowly on/because of the delay. not sure how to make the serial commands run in their own loop so it doesn’t effect what else is going on. the return is 25-57 in serial monitor.

int inPin = 3;
const int ledPin =  2;
const int SpinPin =  1;
unsigned long duration;


void setup() {
  pinMode(ledPin, OUTPUT); // initialize the LED pin as an output:
  pinMode(SpinPin, OUTPUT); // initialize the LED pin as an output:
  pinMode(inPin, INPUT); // make the pin an input:
  Serial.begin (57600);
   
  
}

void loop() {
 unsigned long duration = pulseIn(inPin, HIGH, 200);
   Serial.println(duration);
   delay(1000);
  duration = pulseIn(inPin, HIGH, 200);
     if(duration >=20 && duration <= 50)
  {
    digitalWrite(ledPin, HIGH); // Enables Stepper Current Opto USE RESISTOR!
  }
  else{
    // turn LED off:
    digitalWrite(ledPin, LOW);
  }
  if (duration >=20 && duration <= 50 == HIGH  && digitalRead(4) == HIGH) 
  { 
    digitalWrite(SpinPin, HIGH); // Enables Spindle Opto USE RESISTOR!
  }
  else{
    // turn LED off:
    digitalWrite(SpinPin, LOW); 
  
   
  }
 
}

SECOND

If you are running Mach3 on your laptop how is the 12500Hz signal getting from the laptop to the Arduino? Is there some hardware connected to the laptop? If so what?

[/quote]

mach3 outputs to the LPT port on the back of the laptop, which is running through a db25 cable to a break out adapter which has jumper wires going over to the arduino

Kawgomoo: heres how i stuck the code in there,

This is almost as much fun as going to the dentist.

I don't want you to stick my code in anywhere.

I want you to create a sketch with nothing in it except my code and the necessary setup() stuff. Then I want you to run the code and tell us what numbers you get. Simples.

I hadn't realized you had a laptop with a parallel port - that should work OK. I presume you have a GND connection between the Arduino and the parallel port.

...R

oldvetteguy:
I am not sure if either of these is the cause of your blinking problem, but:

  1. The Pulsein() function by default WAITS for 1 second for the pulse to start if no timeout value is set. In your code the timeout is set for 200 so the Pulsein() function will wait for 200 microseconds for a pulse and then return 0. To quote the reference document " timeout (optional): the number of microseconds to wait for the pulse to start; default is one second (unsigned long) "
  2. The Pulsein() function returns an unsigned long. You have “duration” defined as unsigned int.

good catch, fixed that. didnt help! lol.

Robin2: This is almost as much fun as going to the dentist.

I don't want you to stick my code in anywhere.

I want you to create a sketch with nothing in it except my code and the necessary setup() stuff. Then I want you to run the code and tell us what numbers you get. Simples.

I hadn't realized you had a laptop with a parallel port - that should work OK. I presume you have a GND connection between the Arduino and the parallel port.

Hey now! not funny! I've got 2 weeks of dental fun ahead of me!

i was trying to get out the door for work earlier. it took me a bit to figure out what else is needed to turn your code into a sketch.

int inPin = 3;
unsigned long duration;


void setup() {
  pinMode(inPin, INPUT); // make the pin an input:
  Serial.begin (9600);
  
  
}

void loop() {
  unsigned long duration = pulseIn(inPin, HIGH, 200);
   Serial.println(duration);
   delay(1000);

}

Its running right now. So far i am getting a return of between 27 and 60

Only trouble is without some sort of visual indicator i don't know when, or if, the anomaly is happening. The way i found it before is id sit and let serial print run and when i saw the led flicker i would stop it then scroll backwards till i found the oddball value.

running your code piggybacked into the original sketch i was able to log a "0" in the data stream of 27's - 60's.

will see if i can find another one right now :)

edit

Let the code run a while longer. i am seeing the occasional low return. I saw 14 once and 18 once going through the serial results.

Kawgomoo: Its running right now. So far i am getting a return of between 27 and 60

You seem to have an uncanny ability to be un-systematic and to fail to provide useful information :)

What is providing the input? Can you provide a list of the received values over, say 20 seconds.

When I see that we will decide what to look at next. One small step at a time.

...R

The return seems more stable this morning, the deviation is much lower. the lowest here is a 14, about a 1/3 of the way down.

28
23
28
28
28
28
28
28
28
28
23
28
28
28
27
27
28
28
28
28
28
28
28
27
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
31
28
28
27
28
28
27
28
27
28
28
22
28
28
28
28
27
28
28
28
24
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
27
28
28
28
28
28
28
28
28
28
28
27
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
22
28
28
28
28
28
28
28
28
23
28
28
28
27
27
28
28
28
28
27
28
28
28
28
28
28
28
28
27
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
22
28
31
28
28
28
28
28
27
22
28
28
28
28
27
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
27
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
22
28
28
28
28
28
28
28
28
22
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
14
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
24
28
28
28
28
28
28
28
28
22
28
28
28
28
28
27
25
29
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
27
28
28
28
25
28
28
28
28
28
28
28
28
22
28
28
28
28
28
28
28
28
28
27
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
27
28
28
28
28
28
25
28
28
28
28
28
28
27
28
27
28
37
28
28
29
28
22
28
28
28
28
27
28
28
28
22
28
28
28
28
28
28
27
28
28
28
28
28
28
28
28
27
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
29
28
28
27
28
29
28
28
28
28
28
28
28
28
28
28
28
28
22
28
28
28
27
28
28
28
28
28
28
28
28
28
28
28
28
28
27
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
27
28
28
27
28
28
28
28
22
28
28
27
28
28
28
28
28
22
28
37
28
28
28
28
28
27
28
28
28
28
28
28
28
27
28
28
28
27
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
23
28
28
28
28
28
28
28
28
27
28
28
28
29
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
29
28
28
28
28
28
29
28
28
28
28
28
28
28
28
28
28
24
28
28
28
28
28
28
28
27
22
28
28
28
28
28
28
28
28
27
28
28
28
28
28
28
28
28
43
28
28
28
28
27
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
28
27
28
28
28
29
28
28
28
28
28
28
28
28
28
28
28
28
28
22
28
27
28
27
28
28
28
28
28
27
28
28
28
27
28
27
28
28
28
28
28
28
28
28
28
28
28
27
28
28
28
28
28
28
28
28

Kawgomoo: The return seems more stable this morning, the deviation is much lower. the lowest here is a 14, about a 1/3 of the way down.

If you won't automatically answer all my questions without a reminder I'm not going to bother trying to help. Answer the other question. Last chance.

...R

Regarding reply #14

Your list of values (to me) indicates software issue(s) rather than noise or stability on the input. Here's why:

• Most of the values are 27-29 or ± 1 code count. This could be attributed to the input signal ... seems reasonable.

• One anomalous reading of 14 seems too much of a coincidence to represent 1/2 of a measurement. This could be attributed to a software issue.

• The anomalous readings of 22-24 seems too much of a coincidence to represent 1/4 of a measurement ± 1 code count. This could be attributed to a software issue.

• The anomalous readings of 43 seems too much of a coincidence to represent 1-1/2 of a measurement ± 1 code count. This could be attributed to a software issue.

• The anomalous reading of 31 really messes up my analysis here! Are you sure its not 13 but printed in reverse? (kidding).

Robin2: If you won't automatically answer all my questions without a reminder I'm not going to bother trying to help. Answer the other question. Last chance.

...R

Now i may be an idiot. But whats the other question?

You asked whats supplying the input, that i answered in #7 and #9. A laptop computer running "MACH 3 CNC" is generating the 12500hz signal through its native LPT port. The cable goes into a db-25 jumper box which is where wires are soldered onto the jumpers and brought over the arduino for prototyping {breadboard}

You even remarked that the laptops db25 should be good in #10, so i figured that was already covered. {yes there is a ground from db25 pin 19 to arduino}

Is there something else I'm missing?

dlloyd:
Regarding reply #14

Your list of values (to me) indicates software issue(s) rather than noise or stability on the input. Here’s why:

• Most of the values are 27-29 or ± 1 code count. This could be attributed to the input signal … seems reasonable.

• One anomalous reading of 14 seems too much of a coincidence to represent 1/2 of a measurement. This could be attributed to a software issue.

• The anomalous readings of 22-24 seems too much of a coincidence to represent 1/4 of a measurement ± 1 code count. This could be attributed to a software issue.

• The anomalous readings of 43 seems too much of a coincidence to represent 1-1/2 of a measurement ± 1 code count. This could be attributed to a software issue.

• The anomalous reading of 31 really messes up my analysis here! Are you sure its not 13 but printed in reverse? (kidding).

I do not at all doubt software issues. The charge pump source is notoriously flakey. And i swear i hear the laptop do something inside when the weird results start. Like a tick of a hard drive or something.

Now, this is an old piece of crap machine. granted. And it might have software,driver, god knows what issues.

The intent of this circuit is only to turn off when the 12500 signal is gone, and on when its present. it can be an average over lets say half a second or what not. The only purpose of this circuit is so when you boot up windows, the steppers don’t jump all around from the step/dir pins going undefined as they do. Its not a massive issue, but its annoying and can be unsafe when the spindle goes live under its own free will.

So this little thing needs to work, so i can progress to troubleshooting the rest of the machine. get other software conflicts and what not worked out. But for now, i need to know when i reach over the machine to look at something, its not going to grab me and suck me in. However, when its ON,i need it to be seamless. I don’t want to wonder if my stepper jitter is this thing freaking out or if its the machine/control itself. No need to add more ghosts to chase!

Kawgomoo: So this little thing needs to work, so i can progress to troubleshooting the rest of the machine. get other software conflicts and what not worked out. But for now, i need to know when i reach over the machine to look at something, its not going to grab me and suck me in. However, when its ON,i need it to be seamless. I don't want to wonder if my stepper jitter is this thing freaking out or if its the machine/control itself. No need to add more ghosts to chase!

I guess you could catch those elusive ghosts with an oscilloscope (if available).

The anomalous readings appear to never happen twice in a row and are at least 10 readings apart, so perhaps you could store the results in a circular fashion into a small array of size 3, then just use the median result (ignoring min and max). This should clean things up and give good response at the same time.

EDIT: Alternatively, you do the same thing using 3 variables and shifting the data through them.