USB, Timer, AnalogRead, Interrupt

Oleum

Well-known member
I now have another strange effect on my project. I have the generation of pulses under control, but the readout still gives me problems.
I can send the data to the serial (USB) port, there everything is still ok. But as soon as I actually read on the other side of the port, my pulse generation breaks down. Instead of counting (cnt) up to 14760, it stops counting way too early. It stays that way even after I stop reading the port.
Interestingly, it breaks down not only when I send data to the PC by cable (hardware), but also when I turn on the serial (software) monitor in IDE 2.2.1.
(So it should be possible for you to test the program without the additional hardware I am using)
What does reading to a serial port have to do with writing to a serial port? After all I don't use a handshake which would interrupt the transfer.
The only possibility I suspect so far is the interrupt handling of the USB interface of the Teensy 4.1. which somehow interferes with my AnalogRead or vice versa.

Unfortunately, I'm not that familiar with interrupt handling on the Teensy yet. For example, I don't know to what extent using the timers could mess up the interrupts.

In principle I have three possibilities for the cause:
USB port
AnalogRead
Timer

What do you think about this?


Code:
#include "TeensyTimerTool.h"
#include <ADC.h>
#include <avr/io.h>
#include <avr/interrupt.h>

using namespace TeensyTimerTool;

ADC *adc;

volatile int Numberdiodes = 3648;  // Max count of diodes
volatile int Dioden[3648];          // the array which will be filled every 'pass' while 'jump'ing from diode to diode
volatile long cnt = 0;              // ticks of clock
volatile bool flag = false;

constexpr int start = 48;    // 32 * 4;  // startposition of active diodes in ticks  128 ticks = 64 µs
constexpr int fMPin = 2;     // clock-pin
constexpr int SH = 3;        // SH-pin
constexpr int ICG = 1;       // ICG-pin
constexpr int Baud = 19200;  //38400, 115200, 230400

constexpr int SH_from = 2 * 2;
constexpr int SH_to = 8 * 2;
constexpr int ICG_from = 1 * 2;
constexpr int ICG_to = 16 * 2;
// constexpr int Diodecount = 4;
constexpr int clockrate = 2000000;  // 2 000 000


float Frequ = 135.5;                                   // Hz   135.5     // the desired frequency
volatile long Factor = long((1 / Frequ) * clockrate);  // 29520 Toggle

PeriodicTimer t;  // the ticking timer
PeriodicTimer t1;  // Analog read timer



void setup() {

  Serial.begin(Baud);

  pinMode(fMPin, OUTPUT);
  pinMode(SH, OUTPUT);
  pinMode(ICG, OUTPUT);

  digitalWriteFast(fMPin, HIGH);  // startconditions
  digitalWriteFast(SH, LOW);
  digitalWriteFast(ICG, HIGH);

  adc = new ADC();

  adc->adc0->setReference(ADC_REFERENCE::REF_3V3);  // internal 3.3V ref
  adc->adc0->setAveraging(1);                       // samples per reading
  adc->adc0->setResolution(10);                     // bits of resolution
  adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED);
  adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED);

  t.begin(callback, 250ns);  // callback every 500ns => 1 000 000 Hz Frequence, because of Toggle
  t1.begin(analogs, 0.01s);
}




void callback() {
  cli();                      // Interrupt-test
  cnt++;                     // next tick
  digitalToggleFast(fMPin);  // clock is ticking

  if (cnt >= SH_from && cnt <= SH_to)  // while tick is between 2 and 10
  {
    digitalWriteFast(SH, HIGH);  // SH is HIGH
  } else {
    digitalWriteFast(SH, LOW);  // all the other ticks SH is LOW
  }


  if (cnt >= ICG_from && cnt <= ICG_to)  // while tick is between 1 and 20
  {
    digitalWriteFast(ICG, LOW);  // ICG is LOW
  } else {
    digitalWriteFast(ICG, HIGH);  // all the other ticks ICG is HIGH
  }

  if (cnt >= (Factor * 2)) {  // 29520 ( double Tick)
    cnt = 0;
    digitalWriteFast(SH, LOW);
    digitalWriteFast(ICG, HIGH);
  }
  sei();
}


void analogs() {
  cli();
  //if (flag) {
    int Diode;
    Diode = int(cnt / 4);

    if ((Diode >= start) && (Diode <= Numberdiodes)) {  // All starts with dummy pixels (start). (0->29520) / 2 >= 16

      Dioden[Diode] = adc->adc0->analogRead(A8);

      flag = false;
    }
 // }
  sei();
}




void loop() {  // Whole array send to SerialPort
  
  for (int n = 0; n <= Numberdiodes; n++) {
    if (Dioden[n] != 0) {
      Serial.print("+");
      Serial.print(n);
      Serial.print(" ");
      Serial.print(Dioden[n]);
      Serial.println("-");

      //delayMicroseconds(random(100, 200));
    }
  }
}

I'm not sure if you can do it this way, but I now have two timer routines built in, which should be accessed via interrupt(?)
 
Back
Top