So I've got a waveform that's high for 16ms and low for 2ms repeating forever. I need to recreate that and offsets of that waveform time exactly on a different pin. Right now, I've got an interrupt on the rising edge for the 16ms low/high transistion, and delayMicroseconds() that determines the offset and duration of the high and low pulses. Trouble is, I'm not sure the code I have is as fast and accurate as it could be. And the replicated waveform seems to shift through the full period of the original one. I need it to be locked in.Any suggestions? Here is the code:
//3 is interrupt for Timing
//4 through 11 are Time dependent receivers
//3-11 Pins 12-19
char incomingByte = 0;
int pins[9] =
{
3,4,5,6,7,8,9,10,11
};
void timing()
{
//Serial.println("This is a 0ms Event");
// if(Serial.available() > 0)
// {
incomingByte = Serial.read();
Serial.print("I received");
Serial.println(incomingByte);
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);
delayMicroseconds(16000);
digitalWrite(10, LOW);
delayMicroseconds(2000);
digitalWrite(10, HIGH);
}
//}
void setup() {
// put your setup code here, to run once:
for(int i=0;i<8;i++)
{
pinMode(pins[i], INPUT);
}
pinMode(3,INPUT);
attachInterrupt(1,timing,RISING);
//Begins Serial
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
}
Here's the waveform I'm trying to duplicate:
Desired Waveform
2 Answers 2
If you're looking to speed your code up I would recommend not using digitalWrite
or Serial
. When using digitalWrite it can take quite a few unneeded clock cycles to turn the pin on or off, as a replacement I would suggest looking into using port manipulation.
Example of turning a pin on or off with a preprocessor macro using port manipulation
#define DIGITAL_WRITE_10_HIGH() PORTB = PORTB | B00000100 // Town ON only pin 10
#define DIGITAL_WRITE_10_LOW() PORTB = PORTB & ~B00000100 // Turn OFF only pin 10
Using port manipulation in your code:
#define DIGITAL_WRITE_10_HIGH() PORTB = PORTB | B00000100 // Town ON only pin 10
#define DIGITAL_WRITE_10_LOW() PORTB = PORTB & ~B00000100 // Turn OFF only pin 10
void timing()
{
//incomingByte = Serial.read(); // If needed uncomment, but it's slow
//Serial.println(incomingByte); // If needed uncomment, but it's slow
// Set pinMode in setup()
DIGITAL_WRITE_10_HIGH();
delayMicroseconds(16000);
DIGITAL_WRITE_10_LOW();
delayMicroseconds(2000);
DIGITAL_WRITE_10_HIGH();
}
This code is wrong in many ways.
first of all, timing()
is execute inside an interrupt, this mean that while it is running, all other interrupt and timer stop (delayMicroseconds works because it does not rely on timer, but on know instruction execution time). That mean you have to keep the interrupt funzion faster as possible, or bad things may and will happen. (microseconds still work because it is based on know instruction duration in loop)
For example, Serial is interrupt driven; this may cause a race condition that will freeze the code.
As far as i can understand pin 3 may be a button (in that case you need to apply some antibounce code, just look at the signal create by pressing a button with your oscilloscope to see what happen), so you can just make a digitalRead every loop, if true do your code. So you will keep timing()
out of interrupt.
pinMode()
only needs to be set once, in setup()
. Also, digitalRead()
is really slow: operating directly on the register is a lot faster! see port manipulation
but in your case i would delete all precendent code and do some math to use an ad-hoc PWM, so you will be almost code free and because it will be almost all done by hardware, precision and possible granularity will increase, see secret of arduino PWM
-
If all code is ran inside loop() and you're really looking to squeeze out a few clock cycles I would do the following
void loop() { while(true) { /* Code Here */ } }
as you don't have to worry about the small overhead of recalling loop()Steven10172– Steven101722014年04月14日 09:13:24 +00:00Commented Apr 14, 2014 at 9:13 -
2You've said
pinMode()
can only be set once. I believe that's incorrect. It can be called as often as necessary, at any time.Peter Bloomfield– Peter Bloomfield2014年04月14日 09:15:16 +00:00Commented Apr 14, 2014 at 9:15 -
you are right, but digitalWrite is a mayor speedup, to sqeeze mcu use the PWM and you will have a lot more power with a lot less efford (once you know how to PWM :) )Lesto– Lesto2014年04月14日 09:17:06 +00:00Commented Apr 14, 2014 at 9:17
-
@PeterR.Bloomfield my english is bad, i can't find a way to say what i mean. if you can edit my answer to correct the sentence so it will be correct.. thank youLesto– Lesto2014年04月14日 09:18:43 +00:00Commented Apr 14, 2014 at 9:18
Serial
inside a function that is called by a timer. Never.