Announcement

Collapse
No announcement yet.

Baracuda + Micro

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Davor
    replied
    Originally posted by ODM View Post
    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.

    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...
    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.

    Leave a comment:


  • Orbit
    replied
    Mr. Qiaozhi I know that you do programming help us little ! Otherwise translated Teleno !

    Leave a comment:


  • Michaelo
    replied
    Originally posted by ODM View Post
    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!
    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...

    Mike

    Leave a comment:


  • Qiaozhi
    replied
    Originally posted by Orbit View Post
    Mnogo babica i tako dete osta bez imena . Ivice prevedi im ako zatraze hvala !
    Please make your posts in English, as per the forum rules.

    Leave a comment:


  • Orbit
    replied
    Originally posted by Teleno View Post
    Many grandmas and so the child was left without a name.
    Thank you Teleno !

    Leave a comment:


  • Teleno
    replied
    Originally posted by Orbit View Post
    Mnogo babica i tako dete osta bez imena.
    Many grandmas and so the child was left without a name.

    Leave a comment:


  • ODM
    replied
    Originally posted by Davor View Post
    So in effect I can't rely on AVR to provide jitter-less digital output?
    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.

    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:


  • Orbit
    replied
    Mnogo babica i tako dete osta bez imena . Ivice prevedi im ako zatraze hvala !

    Leave a comment:


  • Davor
    replied
    Originally posted by ODM View Post
    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!
    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?

    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:


  • ODM
    replied
    Originally posted by Teleno View Post
    it's extremely easy to connect A/D and D/A converters through I2C and SPI to attiny and atmega. I have done both
    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%B2S

    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:


  • ODM
    replied
    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:


  • Michaelo
    replied
    Here's the code with the delayMicroseconds()

    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;
    }
    Works just like before....

    TX pulse = 100.0uS
    Sample Pulse 1 = 45.60us
    Sample Pulse 2 = 45.60uS
    Frequency = 641.0 Hz
    Click image for larger version

Name:	2016-04-11_032550.jpg
Views:	1
Size:	338.8 KB
ID:	345516
    Last edited by Michaelo; 04-11-2016, 02:29 AM. Reason: Added pic

    Leave a comment:


  • Michaelo
    replied
    Originally posted by Teleno View Post
    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.
    Appreciate that, it appears the processor does that for you... but you get the idea..

    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
    Last edited by Michaelo; 04-11-2016, 12:58 AM. Reason: Another idea!

    Leave a comment:


  • Teleno
    replied
    Originally posted by Michaelo View Post
    I 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!!!

    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;
    }
    Generally speaking ISR should complete quickly but as we are only generating one interrupt this code seems perfectly reasonable...

    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
    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.

    Leave a comment:


  • 6666
    replied
    Test!!! Code!!!

    What are you compiling it in ?

    Leave a comment:

Working...
X