Originally posted by ODM
View Post
Announcement
Collapse
No announcement yet.
Baracuda + Micro
Collapse
X
-
OK, that makes a bit more sense. At first it seemed AVR lapses these clocks randomly, but if I make sure it gets equal treatment on every interrupt, the latency remains the same, and jitter-free. Thanks.
-
Mr. Qiaozhi I know that you do programming help us little ! Otherwise translated Teleno !
Leave a comment:
-
The jitter you speak of, could it manifest in slight glitches on otherwise perfect pulses? I ask because while monitoring the pulse generated with different code samples, some exhibited very slight jitter and it was not extraneous noise or interference...Originally posted by ODM View PostOne can also nest interrupts by enabling them after entering an interrupt. This can be done as far as stack remains for saving previous context.
Also, AVR has an interrupt ambiguity of 2 cycles as instructions run for 1-3 cycles. This makes for 100ns jitter at 20MHz, unless accounted for somehow such as sleeping cpu before timer interrupt or by reading timer value. This is probably of no matter for a run of the mill PI detector though!
Mike
Leave a comment:
-
You can. It is only interrupt latency related. And like I wrote in the same post, that can be fixed by reading timer value and adding a few idle cycles, or sleeping the cpu before interrupt. This can be done in interrupt "before" interrupt for example. And timer hardware output pins have no latency related jitter of course.Originally posted by Davor View PostSo in effect I can't rely on AVR to provide jitter-less digital output?
Poorly regulated or ground noisy conditions, logic gate timers can have equal jitter or worse. So that shouldn't be an issue for performance equal to most "seasoned" PI designs that get so much love...
Leave a comment:
-
Mnogo babica i tako dete osta bez imena .
Ivice prevedi im ako zatraze hvala !
Leave a comment:
-
This is a completely new moment for me. I was not aware of this. So in effect I can't rely on AVR to provide jitter-less digital output?Originally posted by ODM View PostAlso, AVR has an interrupt ambiguity of 2 cycles as instructions run for 1-3 cycles. This makes for 100ns jitter at 20MHz, unless accounted for somehow such as sleeping cpu before timer interrupt or by reading timer value. This is probably of no matter for a run of the mill PI detector though!
Say, if I want to clock a VLF coil with AVR, I may expect some FM noise as a consequence of jitter. And there is no way around it unless it is the only thing AVR does, which renders it to a mere CMOS divider. Bummer.
Leave a comment:
-
I2S is a different beast, though. Many 96/192kHz AD/DA for audio purposes use this type of interface and it is popular for audio DSP as well. https://en.wikipedia.org/wiki/I%C2%B2SOriginally posted by Teleno View Postit's extremely easy to connect A/D and D/A converters through I2C and SPI to attiny and atmega. I have done both
The good thing about I2S is the hardware is cheap and numerous and generally interfaces in a similar manner. The bad thing is its bit clock that can't be stopped even by the master, and AVR doesn't have dedicated hardware for catching bytes from a continuous stream in an elegant manner.
General AVR SPI can't load/read while transmission is in progress so actual bit rate will depend on SPI handling latency. UART in SPI mode is something I used for updating a two-byte DAC value by timer interrupt, which took less cycles than sending one complete byte did. It'll depend on the application if it's worth it or not, and one can always argue that a heavier mcu should be used instead.
STM32 will handle I2S rather nicely, though it's a space shuttle compared to PIC/AVR when actually digging into how the hardware works. I2S hardware might not be that applicable for PI detectors as there's often some bitstream filters and whatnot in the deltasigma type converters that cuts on the actual bandwidth, but 24-bit 192kHz on a few channels might be very welcome for VLF detectors.
Leave a comment:
-
One can also nest interrupts by enabling them after entering an interrupt. This can be done as far as stack remains for saving previous context.
Also, AVR has an interrupt ambiguity of 2 cycles as instructions run for 1-3 cycles. This makes for 100ns jitter at 20MHz, unless accounted for somehow such as sleeping cpu before timer interrupt or by reading timer value. This is probably of no matter for a run of the mill PI detector though!
Leave a comment:
-
Here's the code with the delayMicroseconds()
Works just like before....Code:void do_isr() { unsigned long now = 0; unsigned long then = 0; if (in_long_isr) { return; } in_long_isr = true; PINC = 0x01; for(int i = 0; i < TX_PULSE; i++) { __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t"); __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t"); __asm__("nop\n\tnop\n\tnop\n\t"); } PINC = 0x01; for(int i = 0; i < PULSE_1_DELAY; i++) { __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t"); __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t"); __asm__("nop\n\tnop\n\tnop\n\t"); } PINC = 0x02; for(int i = 0; i < PULSE_1; i++) { __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t"); __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t"); __asm__("nop\n\tnop\n\t"); } PINC = 0x02; for(int i = 0; i < PULSE_1_DELAY; i++) { __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t"); __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t"); __asm__("nop\n\tnop\n\t"); } PINC = 0x04; for(int i = 0; i < PULSE_2; i++) { __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t"); __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t"); __asm__("nop\n\tnop\n\t"); } PINC = 0x04; in_long_isr = false; }
TX pulse = 100.0uS
Sample Pulse 1 = 45.60us
Sample Pulse 2 = 45.60uS
Frequency = 641.0 Hz
Leave a comment:
-
Appreciate that, it appears the processor does that for you... but you get the idea..Originally posted by Teleno View PostBy default interrupts are not interruptable. The initial cli() and final sei() instructions in the ISR are unnecessary. It also means that delay() which interrupt-based cannot service its interrupts during the 310us taken by your ISR.
As I said above it not an ideal solution, even using multiple delayMicroseconds inside an interrupts has some issues...
I would have preferred to generate the pulses independently but apparently I would need a faster clock frequency...
I will probably change from using delayMicroseconds to using a counter/timer loop to achieve the same result later on...
Mike
Leave a comment:
-
By default interrupts are not interruptable. The initial cli() and final sei() instructions in the ISR are unnecessary. It also means that delay() which interrupt-based cannot service its interrupts during the 310us taken by your ISR.Originally posted by Michaelo View PostI solved the interrupt issue but not exactly as I would have liked but this way it's a great deal easier. I simply move the pulse code inside the new timer ISR...
You can see the timing I'm using in the defines at the top of the code... some may need tweaking...
Test!!! Code!!!
Generally speaking ISR should complete quickly but as we are only generating one interrupt this code seems perfectly reasonable...Code:#include <TimerOne.h> #define CYCLE_TIME 1662 // 0.0015625 Seconds @ 640 PPS // added 100 to 1562 to make is closer to 640pps // #define TX_PULSE 100 //(100µs) 100µs #define PULSE_1_DELAY 20 //( 20µs) Delay before Sample Pulse 1 #define PULSE_1 45 //( 45µs) Sample 1 Pulse Duration #define PULSE_2_DELAY 100 //( 100µs) Delay between Sample Pulse 1 and Pulse 2 #define PULSE_2 45 //( 45µs) Sample 2 Pulse Duration 45µs /* Total Pulses Time 310 ----------------------------- Cycle Time 1562 Pulse Times -310 Delay till next cycle 1252 Actual cycle time is 1/1562 µs = ~640 */ volatile bool in_long_isr = false; // True if in long interrupt int cnt = 0; void setup() { pinMode (A0, OUTPUT); pinMode (A1, OUTPUT); pinMode (A2, OUTPUT); digitalWrite (A0, LOW); digitalWrite (A1, LOW); digitalWrite (A2, LOW); Serial.begin(9600); Timer1.initialize(CYCLE_TIME); Timer1.attachInterrupt(do_isr); } void loop() { Serial.println(cnt++); delay(100); } void do_isr() { if (in_long_isr) { return; } in_long_isr = true; cli () ; PINC = 0x01; delayMicroseconds(TX_PULSE); PINC = 0x01; delayMicroseconds(PULSE_1_DELAY); PINC = 0x02; delayMicroseconds(PULSE_1) ; PINC = 0x02; delayMicroseconds(PULSE_2_DELAY); PINC = 0x04; delayMicroseconds(PULSE_2); PINC = 0x04; sei () ; in_long_isr = false; }
You may note I'm using the analogue pins, that's because I've used all of the others for the Keys and LCD...
As usual, if you find any error please be polite when posting...
I've tested and scoped the pulses and everything look good, next to get the keys and LCD up and running...
Mike
Leave a comment:

Leave a comment: