Hello,
I am currently using an Arduino Uno to output three square wave pulses to trigger a few systems independently and with good timing.
The issue I wanted to ask for advice on is as follows,
I am trying to output a constant, uninterrupted 20 Hz 10 microsecond High/Low pulse train while being able to constantly sense for a button push which should yield another pair of 10 microsecond High/Low pulses on other channels/pins.
So far all my attempts have had to either interrupt the 20 Hz output or not left the loop from the 20 Hz signal to see anything else.
So every 50mS you want a 10uS wide pulse?
And while that is going on, read a button and output another 10uS wide pulse?
10uS is 160 clock cycles at 16 MHz, should be doable.
Somthing like this in void loop. Declare all the variables, pinMode's in setup, etc.
All time variables are unsigned long.
void loop(){
currentMicros = micros();
elapsedMicros = currentMicros - previousMicros;
if (elapsedMicros >=50mS){
previousMicros = previousMicros + 50mS;
PORTD = PORTD | B00000100; // use PORTD, bit 2 for an output for example
delayMicroseconds(10);
PORTD = PORTD & B11111011;
} // end 20Hz time check
if (digitalRead (buttonPin) == LOW){ // happens between 20Hz pulses
PORTD = PORTD | B00001000; // use PORTD, bit 3 for an output for example
delayMicroseconds(10);
PORTD = PORTD & B11110111;
delayMicroseconds(10);
PORTD = PORTD | B00001000; // use PORTD, bit 3 for an output for example
delayMicroseconds(10);
PORTD = PORTD & B11110111;
}
} // end loop
This will need some more fleshing out, clarify when button press pulses are to occur, do they need debounce, how long between pulses, etc.
If you need absolute precision you could program timer1 to output that signal in hardware. If you need multiple devices you can add some external AND gates and combine the signal with the output of other pins.
I would like it to be as precise as possible fungus,
although jitter shouldn't matter with this regime (I hope).
The 20 Hz signal is for a laser flashlamp sync input, the TTL pulse tells the flashlamp to fire.
The user button press then send two TTL pulses, one to trigger an SCR circuit close and a second after a delay to tell the laser Q-switch to toggle.
I was initially planning to do this with LabView and a National Instruments card but the money for that never seems available,
so today a friend handed me his Arduino and said it was worth a try.
Okay, so I have this working fine as an "uninterrupted" 20Hz signal for the laser flashlamps,
however the buttonpush solution isn't working as I would like.
Due to the relatively long time of my button press I am getting a pulse train from my second output rather than the single shot I would like.
I have tried to set the second pulse to only fire once during any ~0.5s period but I've not been able to get that working.
Otherwise I was going to switch from this regime to using a TTL pulse we do have available to trigger the Arduino rather than my button press.
pardon the poor photo of the scope screen, for the purpose of easy viewing next to the 20Hz signal I've also set the pulse widths higher & am flashing LEDs thus the halved voltage.
if (digitalRead (buttonPin) == LOW){ // happens between 20Hz pulses
PORTD = PORTD | B00001000; // use PORTD, bit 3 for an output for example
delayMicroseconds(10);
PORTD = PORTD & B11110111;
delayMicroseconds(10);
PORTD = PORTD | B00001000; // use PORTD, bit 3 for an output for example
delayMicroseconds(10);
PORTD = PORTD & B11110111;
}
Store the time of the initial button press, send out the pulse or two, and don't let another pulse occur until some time has elapsed
// look for button press, and flag to show if debouncing is occurring
if (digitalRead (buttonPin) == LOW) && (debouncing == 0)){ // happens between 20Hz pulses
debounceStart = currentMicros; // capture time of button press, & set flag
debouncing = 1;
PORTD = PORTD | B00001000; // use PORTD, bit 3 for an output for example
delayMicroseconds(10);
PORTD = PORTD & B11110111;
}
if (debouncing == 1){
elapsedDebouncing = currentMicros - debounceStart; // hw much time has passed?
if (elapsedDebouncing <=debounceTime){
debouncing = 0; // long enough, clear the flag
}
}
Any chance I could ask for more advice on this,
I see what the code is doing but I can't understand why it isn't debouncing,
it isn't even waiting for a button push anymore.
Anything obvious with whats here?
int buttonPin = 8; // Pin 8 for button push user input
long currentMicros, elapsedMicros, previousMicros; // All time variables are unsigned long
long debouncing, debounceStart, elapsedDebouncing;
long debounceTime = 100000;
void setup()
{
pinMode(buttonPin, INPUT); // Button push input to start fire command
DDRD = DDRD | B01111100; // this is safer as it sets pins 2 to 7 as outputs
// without changing the value of pins 0 & 1, which are RX & TX
digitalWrite(buttonPin, LOW);
}
void loop()
{
currentMicros = micros(); //
elapsedMicros = currentMicros - previousMicros; //
if (elapsedMicros >=500000) // 50mS :. 20Hz
{
previousMicros = previousMicros + 50000;
PORTD = PORTD | B00100000; // use PORTD, bit 5 for an output for example
delayMicroseconds(10); // PORTD cmds pin 7 to 0
PORTD = PORTD & B11011111; //
} // end 20Hz time check
// look for button press, and flag to show if debouncing is occurring
if (digitalRead (buttonPin == HIGH) && (debouncing == 0)) // happens between 20Hz pulses
{
debounceStart = currentMicros; // capture time of button press, & set flag
debouncing = 1;
delay(5);
PORTD = PORTD | B00010000; // use PORTD, bit 4
delayMicroseconds(10);
PORTD = PORTD & B11101111;
}
if (debouncing == 1)
{
elapsedDebouncing = currentMicros - debounceStart; // hw much time has passed?
if (elapsedDebouncing <=debounceTime)
{
debouncing = 0; // long enough, clear the flag
digitalWrite(buttonPin, LOW);
}
}
} // end loop
Fix this:
Change to INPUT_PULLUP, enable internal pullup resistor - look for a LOW when read to show button is pushed (connected to Gnd):
pinMode(buttonPin, INPUT_PULLUP); // Button push input to start fire command
I would just use pinMode on the individual pins, less chance to hose something:
DDRD = DDRD | B01111100; // this is safer as it sets pins 2 to 7 as outputs
// without changing the value of pins 0 & 1, which are RX & TX
Delete this - it turns off the internal pullup resistor if used after pinMode:
digitalWrite(buttonPin, LOW);
if (elapsedMicros >=500000) too many 0's - this is 0.5S, you wanted 0.05S
Thanks again CrossRoads, getting more and more used to the commands with this.
However the Arduino is still not waiting for a button push, there is just a continuous roll of pulses from the fireCMD pin 4.
I can see the 5V sitting on pin 8 from my multimeter, and it does go to zero on a button push.
int buttonPin = 8; // Pin 8 for button push user input
int flashCMD = 5; // Pin 5 for flash lamp 20Hz cmd
int fireCMD = 4; // Pin 4 for Qswitch fire cmd
int dischCMD = 3; // Pin 3 for SCR close cmd for discharge
long currentMicros, elapsedMicros, previousMicros; // All time variables are unsigned long
long debouncing, debounceStart, elapsedDebouncing; //
long debounceTime = 500000; // How long to wait before another fireCMD allowed (0.5s)
void setup()
{
pinMode(buttonPin, INPUT_PULLUP); // Button push input to start fire command
pinMode(flashCMD, OUTPUT); //
pinMode(fireCMD, OUTPUT); //
pinMode(dischCMD, OUTPUT); //
}
void loop()
{
currentMicros = micros(); //
elapsedMicros = currentMicros - previousMicros; //
if (elapsedMicros >=50000) // 50mS :. 20Hz
{
previousMicros = previousMicros + 50000;
PORTD = PORTD | B00100000; // use PORTD, bit 5 for an output for example
delayMicroseconds(10); // PORTD cmds pin 7 to 0
PORTD = PORTD & B11011111; //
} // end 20Hz time check
// look for button press, and flag to show if debouncing is occurring
if (digitalRead (buttonPin == LOW) && (debouncing == 0)) // happens between 20Hz pulses
{
debounceStart = currentMicros; // capture time of button press, & set flag
debouncing = 1;
delay(5);
PORTD = PORTD | B00010000; // use PORTD, bit 4
delayMicroseconds(10);
PORTD = PORTD & B11101111;
}
if (debouncing == 1)
{
elapsedDebouncing = currentMicros - debounceStart; // how much time has passed?
if (elapsedDebouncing <=debounceTime)
{
debouncing = 0; // long enough, clear the flag
}
}
} // end loop