I built the electronic circuit, that suppose to run 70000 cycles, so I made a code to read number of cycles and display the cycle count on the LCD.
Due to the contact bouncing (I suppose, picture from the scope will be added), my counter is not counting properly. Sometimes my code start counting properly and sometimes it can not keep counting, it stop always at LOW signal from the countpin, even though I checked my circuit that is still functioning every cycle. What should I change from my code?
My code is as follow:
/*
* RevB: made counter a long to be able to count more cycles
* simple counter to count number of cycles of configuration contactor
* Measures state of A1 that is either pulled up by internal node Arduino
* or pulled to gnd by the contactor
*
*/
#include <LiquidCrystal.h>
#define countpin A1
long counter=0;
long bouncedelay_ms= 1200;
bool contact;
bool prev_contact;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // select the pins used on the LCD panel
// the setup routine runs once when you press reset:
void setup() {
// initialize the LCD
pinMode(countpin, INPUT);
lcd.begin(16, 2);
delay(250);
//stared twice dunno why, but does not hurt either
lcd.begin(16, 2);
delay(250);
lcd.setCursor(0, 0);
lcd.print("Counter: ");
lcd.print(counter);
}
// the loop routine runs over and over again forever:
void loop()
{
// read the input on analog pin 0:
if(digitalRead(countpin)==HIGH || counter ==0)
{
contact=true;
lcd.setCursor(0, 1);
lcd.print("open ");
lcd.setCursor(0, 0);
lcd.print("Counter: ");
lcd.print(counter);
delay(bouncedelay_ms);
}
else
{
contact=false;
if (prev_contact==true)
{
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("closed");
counter++;
lcd.setCursor(0, 0);
lcd.print("Counter: ");
lcd.print(counter);
delay(bouncedelay_ms);
}
}
prev_contact=contact;
//delay(100); // delay in between reads for stability
}
As see in the picture, digitalRead(countpin) == HIGH at 20V (red line) (contact open), digitalRead(countpin) ==LOW at 0V (contact closed),
The blue line is the current running through contact.
My circuit is build as follow:
Thanks for your answer. I forgot to also added how I connect my circuit to arduino pin. From my circuit, I connect the Device under test voltage signal and the voltage signal from the switch.. so it would be either be 20V or 0V. Before connect to Arduino countpin, i did add a zener diode and a resistor to protect the arduino.
To enable internal pullup I think you need INPUT_PULLUP here.
That is 1.2 seconds, which seems quite a long time for a debounce. From the scope trace it appears the bouncing takes much less than 5 ms. Depending on how often the contactor operates, it might miss cycles.
1,000,000 / 70,000 is 14.28~~~ microseconds. Contact bounce should go on for more than 1000 micros. I don't see a button in the code so please tell if the signal is made mechanically?
There are gear tooth counters that without contact do detect gear teeth turning at high rpm with zero bounce. They can detect saw teeth too, They make a magnetic field and detect moving metal as it bends the field with a Hall sensor.
IR beam break or reflection can do the same.
Yes there is no button, the signal is from the voltage over the 2 cables to the Device Unter Test and the switch on my circuit. If there is voltage -> HIGH, if no voltage -> LOW
Just to gather data to see what you can get since you need a very fast loop() to capture 70,000 Hz waves and instead of states you want to detect transitions like LOW to HIGH and count those per second.
I did just that when checking out bounce as part of writing better debounce routines than I had in 2012. I caught bounces that micros measured as 8 and 12 micros long ... but I was looking for stable states after the bounce. My button is a jumper that I ground on the grounded USB port box, and how 'dirty' I could make the contact to simulate a crappy button (bad case proof design).
Arduino micros at least on 16MHz AVR chips 'ticks' once every 4 micros (the low 2 bits are always zero, check it and be sure!) so accurate timing per wave is not possible. There are much faster Arduinos and compatibles (Teensy 4.1 is 600MHz IIRC) though I can't say if the Arduino micros() function works better on those... it could.
If you feed the test signal to counter/clock timer chip that tells the Arduino once every 256 or more waves, the per wave timing error of the average will be smaller assuming a regular signal and that external hardware will carry a lot of the load.
The switch is a manual switch which always closed (always pass current through). My device under test is a normally open contactor (also a switching device), which would be closed once every 6 - 7 seconds or so. My purpose of counter is to count how many times the device under test closed (finish 1 cycle)/
I have debounce code that is fast. It watches for 3.5 ms of stable pin state but that is when the pin is read once per 512 micros. With a read every 256 the time is half so much, it won't debounce dirty switches so I read slower for those.
How long the bounce goes on and how long the LOWs and HIGHs of the bounce take all force the total time for bounce + stable.
What gaps do you see on the scope during bounce? The pin stable time to determine that bounce has ended must be longer than actual between bounce changes time... I give it extra because I can but you may have to cut it fine.
In my loop(), one function watches the pin and updates a global status byte. the bits of that byte are a picture of the reads taken at regular intervals (512 micros but can be different). OTHER functions read the byte. 0b10000000 means switch transition from open to close and stable for 7 reads for example.
But the pin can be read much faster and the pin history byte could be n unsigned long with reads 32 micros apart to show 1024 micros history looking for 992 micros of same-read 'stable' after however long the bounce takes.