Serial.println() will not finish print statements

Discussion about Z-Uno product. Visit http://z-uno.z-wave.me for more details.
Post Reply
Alphaprot
Posts: 4
Joined: 07 Jul 2020 15:32

Serial.println() will not finish print statements

Post by Alphaprot »

First things first - I have not put my Z-Uno Rev. 1 to a good use as of now, so I am trying to change that by creating a controller board (PCB with some peripherals such as an I2C RTC, a DAC circuitry for setting analog 0-10V values and a few more items.
The Z-Uno is meant to sit piggyback on this board.

I am currently trying to test and debug my hardware (because I realized I need to add some hardware changes on my PCB, but it goes without saying that I want to make sure it actually works somewhat as intended by testing and debugging first before ordering my second revision).

The current code (lacking some functionality, e.g. RTC is not really used at the moment) can be found here:
https://pastebin.com/RHHUYCDG
It generously uses

Code: Select all

Serial.println()
statements to output some information via USB Serial (I know about the 115200 baud rate setting for USB connections).
Unfortunately, the serial output quits working after just a few lines and in the middle of a print statement (the last line is incomplete):

Code: Select all

22:15:00.116 -> Opened serial connection.
22:15:00.116 -> Initializing DAC...
22:15:00.116 -> Reading 1 byte 
I noticed already that print-statements in the setup()-scope might fail if the command is executed too fast after bringing up the Serial interface (adding a small delay did the trick), but what is the underlying problem here and how to deal with it?
I have the vague assumption that I overflow my TX buffer, but that might not be the reason, is it?

Any help is appreciated, especially since I am pretty inexperienced with Z-Unos.
User avatar
PoltoS
Posts: 7562
Joined: 26 Jan 2011 19:36

Re: Serial.println() will not finish print statements

Post by PoltoS »

Since we are talking of Z-Uno 1, please wait till 8th of August until our R&D and support of that older version is back from vacations.
p0lyg0n1
Posts: 242
Joined: 04 Aug 2016 07:14

Re: Serial.println() will not finish print statements

Post by p0lyg0n1 »

Hello. First about Serial, it uses native USB on the first-generation ZUno, built into the chip itself, so it is not very well suited for detailed debugging, especially the device start area. It is quite suitable for displaying repetitive actions in the loop, but you can skip the whole beginning due to the start of the chip's peripherals. It is better to use an external USB-Serial adapter on pin TX0 (Serial0).
I quickly looked through the code, I can try it on my own on my hardware, although I don't have all the peripherals. While confused in the code is this:

Code: Select all

// ...
float voltage[3] = { 3, 6, 9 };
// ...
uint8_t newAddr[8];
Such announcements can lead to stack overflow on the 1st ZUno. There's only 140 bytes of stack for everything. It is better to move them to the global area - perhaps the problem is because of this. On the 2nd version, there are no such problems with the stack anymore.
I'll try to run your code, maybe I can test it without the peripherals.

Best regards,
Alex.
p0lyg0n1
Posts: 242
Joined: 04 Aug 2016 07:14

Re: Serial.println() will not finish print statements

Post by p0lyg0n1 »

Here, try this code (I changed yours a little to just change Serial) with an external adapter connected to RX0, debugging will be much easier

Code: Select all

#include "SPI.h"
#include "Wire.h"
#include "ZUNO_OneWire.h"

#define SPI_CS 8
SPISettings spi_settings = SPISettings(8000000, MSBFIRST, SPI_MODE0);

#define oneWirePin 12
// MAX31820 uses default 12 bit for 0.05 °C resolution, requires > 750ms conversion time

OneWire oneWire(oneWirePin);
uint8_t MAX31820addr[8][4];  //2-d array  for 4 MAX31820 ROM addresses
uint16_t RTCaddress = 0xA2;  //PCF85263A I2C target write address; read target address is 0xA3
                             //ZUNO_SETUP_CHANNELS(ZUNO_SENSOR_BINARY())


ZUNO_SETUP_ISR_INT0(ofenSetError);
ZUNO_SETUP_ISR_INT1(RTCseconds);

#define FET1 16
#define FET2 15
#define FET3 14
#define FET4 3

#define INT_RTC 18
#define INT_OFEN 17
#define INT_LFTG 19

#define LED_OFEN 21
#define LED_LFTG 20

#define MY_SERIAL Serial0
//variables
float v_resistorLadder = 4.7;  //Spannung der Resistor Ladder Op-Amp

uint8_t ofenDefault = 7;                  //Standardheizleistung Ofen in kW
uint8_t lueftungDefault = 2;              //Standardstufe Lüftung
uint8_t ofenHeizleistung = ofenDefault;   //Aktuelle Heizleistung Ofen in kW
uint8_t lueftungStufe = lueftungDefault;  //Aktuelle Stufe Lüftung

float tempAussen;
float tempZuluft;
float tempFortluft;
float tempAbluft;

//bypass settings
float tMax = 20;  //default 24
float tMin = 13;  //default 13

uint8_t incrementLueftung = 0;
uint8_t incrementOfen = 0;

uint8_t retryCounter = 0;
uint8_t deviceCount = 0;              //number of discovered OneWire-Devices on the bus
uint16_t borDetectionInterval = 300;  //seconds between Brownout-Checks
uint16_t temperaturePollingIntervall = 300;
uint16_t RTCintCounter = 0;  //counter variable for periodic (1s) RTC interrupts, reset after 300s

boolean FET1_on = false;  //Koppelrelais Ofen
boolean FET2_on = true;   //Koppelrelais Lüftung
boolean FET3_on = false;
boolean FET4_on = true;

boolean ofenOn = false;
boolean lueftungOn = true;
boolean ofenError = false;      //Störmeldung Ofen D1
boolean lueftungError = false;  //Störmeldung Lüftung D2
boolean lueftungBypassOffen = false;

boolean RTCalarm1 = false;  //mm:dd:hh:mm:ss
boolean RTCalarm2 = false;  //hh:mm and weekday

//void DACpowerState(int channel = 0, char* state = "off"); (SDCC compiler error, optional args werden nicht kompiliert?)
//void lueftungSetState(char* state, int duration = 0);

void RTCseconds() {
  RTCintCounter++;
}

void ofenSetError() {
  ofenError = true;
  digitalWrite(LED_OFEN, LOW);
}

uint8_t newAddr[8];
void setup() {
  MY_SERIAL.begin(115200);
  SPI.begin();
  pinMode(SPI_CS, OUTPUT);
  digitalWrite(SPI_CS, HIGH);
  delay(1);
  Wire.begin();
  //Wire.setWireTimeout(3000, true);  //abort transmission after 3000 us and reset communication module

  zunoExtIntMode(ZUNO_EXT_INT0, RISING);
  zunoExtIntMode(ZUNO_EXT_INT1, RISING);

  // set up inputs
  pinMode(INT_LFTG, INPUT);
  pinMode(INT_OFEN, INPUT);
  pinMode(INT_RTC, INPUT);
  // set up outputs
  pinMode(FET1, OUTPUT);
  pinMode(FET2, OUTPUT);
  pinMode(FET3, OUTPUT);
  pinMode(FET4, OUTPUT);
  pinMode(LED_LFTG, OUTPUT);
  pinMode(LED_OFEN, OUTPUT);
  digitalWrite(FET1, LOW);
  digitalWrite(FET2, LOW);
  digitalWrite(FET3, LOW);
  digitalWrite(FET4, LOW);
  digitalWrite(LED_LFTG, LOW);
  digitalWrite(LED_OFEN, LOW);

  delay(1000);
  MY_SERIAL.println("Opened serial connection.");
  //Set up DAC registers
  DACinit();

  //Set up RTC registers
  RTCinit();

  MY_SERIAL.println("Probing OneWire bus...");
  oneWire.reset_search();
  deviceCount = 0;
  
  while (oneWire.search(newAddr)) {
    deviceCount++;
    MY_SERIAL.print("New device found:");

    for (int i = 0; i < 8; i++) {
      MAX31820addr[deviceCount][i] = newAddr[i];
      MY_SERIAL.print(newAddr[i], HEX);
      MY_SERIAL.print(" ");
    }
    MY_SERIAL.println();
  }
  MY_SERIAL.println("No more devices found.");
}

void loop() {
  //testing
  MY_SERIAL.println("LOOP>>>");
  if (incrementOfen > 13) incrementOfen = 0;
  if (incrementLueftung > 3) incrementLueftung = 0;
  if (RTCintCounter == 20) {
    DACsetVoltage(1, ofenCalcVoltage(ofenHeizleistung));
    DACsetVoltage(2, lueftungCalcVoltage(ofenHeizleistung));
    ofenHeizleistung = incrementOfen;
    lueftungStufe = incrementLueftung;
  }


  //end testing
  if (RTCintCounter == 60) {
    MY_SERIAL.println("60s elapsed.");
    delay(16);  //maximum time for periodic interrupt flag clearance is 2* 1/128 = 16 ms
    RTCgetFlags();
  }

  if (RTCintCounter == 300) {
    MY_SERIAL.println("300s elapsed.");
    RTCintCounter = 0;
    MAX31820getAllTemperatures();
    DACborDetection();
  }
}

void DACinit() {
  MY_SERIAL.println("Initializing DAC...");
  DACread(0x0A);               //clear POR Bit by reading status register
  DACwrite(0x0A, 0x03, 0x00);  //set gain B9:B8 of 1x for both channels
  DACwrite(0x08, 0x00, 0x00);  //set VREF to VDD for both channels
  DACsetVoltage(1, ofenCalcVoltage(ofenHeizleistung));
  DACsetVoltage(2, lueftungCalcVoltage(lueftungStufe));
  if (ofenOn) ofenSetState("on");
  if (!ofenOn) ofenSetState("off");
  if (lueftungOn) lueftungSetState("on");
  if (!lueftungOn) lueftungSetState("off");
  MY_SERIAL.println("Done initzializing DAC.");
}
void DACborDetection() {
  MY_SERIAL.print("Checking for BOR-related memory corruption on DAC...");
  word borWord = DACread(0x0A);
  boolean borBitSet = bitRead(borWord, 8);

  if (borBitSet == true) {
    MY_SERIAL.println("FAILED! Reinitizialing DAC.");
    DACinit();  //reinitialize DAC with current values
  } else {
    MY_SERIAL.println("PASS.");
  }
}
void DACsetVoltage(int channel = 0, float voltage = 0) {  //writes register 0x00 or 0x01 respectively
  MY_SERIAL.print("Setting wiper value of ");
  if (voltage > 2 * v_resistorLadder) voltage = 2 * v_resistorLadder;
  if (voltage < 0) voltage = 0;

  byte wiperPosition = (int)(((voltage / 2) / v_resistorLadder) * 256);
  MY_SERIAL.print(wiperPosition);

  if (channel == 1) {
    MY_SERIAL.println(" for oven...");
    DACwrite(0x00, 0x00, wiperPosition);
  }
  if (channel == 2) {
    MY_SERIAL.println(" for lueftung...");
    DACwrite(0x01, 0x00, wiperPosition);
  }



  //confirm correct output voltage is set in DAC register
}

void DACpowerState(int channel = 0, char *state = "off") {  //writes register 0x09, if channel 0 is used, both channels are switched
  if (channel == 0) {
    if (!strcmp(state, "on")) {
      DACwrite(0x09, 0x00, 0x00);
      ofenOn = true;
      lueftungOn = true;
    }
    if (!strcmp(state, "off")) {
      DACwrite(0x09, 0x00, 0x03);
      ofenOn = false;
      lueftungOn = false;
    }
  } else if (channel == 1) {
    if (!strcmp(state, "on")) {
      byte cmd = 0x00;
      bitWrite(cmd, 1, lueftungOn);
      DACwrite(0x09, 0x00, cmd);
      ofenOn = true;
    }
    if (!strcmp(state, "off")) {
      byte cmd = 0x01;
      bitWrite(cmd, 1, lueftungOn);
      DACwrite(0x09, 0x00, cmd);
      ofenOn = false;
    }
  } else if (channel == 2) {
    if (!strcmp(state, "on")) {
      byte cmd = 0x00;
      bitWrite(cmd, 0, ofenOn);
      DACwrite(0x09, 0x00, cmd);
      lueftungOn = true;
    }
    if (!strcmp(state, "off")) {
      byte cmd = 0x02;
      bitWrite(cmd, 0, ofenOn);
      DACwrite(0x09, 0x00, cmd);
      lueftungOn = false;
    }
  }
}

void DACwrite(byte writeAddr, byte data2, byte data1) {
  if (retryCounter < 3) {
    MY_SERIAL.print("Writing ");
    MY_SERIAL.print(data2, HEX);
    MY_SERIAL.print(data1, HEX);
    MY_SERIAL.print(" at DAC address ");
    MY_SERIAL.print(writeAddr, HEX);
    MY_SERIAL.print(" ...");
    byte cmdReturn;
    writeAddr = writeAddr << 3;
    byte cmdByte = writeAddr;  // 00 write 0 error bit, so nothing has to be added
    SPI.beginTransaction(&spi_settings);
    digitalWrite(SPI_CS, LOW);
    delay(1);
    SPI.transfer(cmdByte);
    cmdReturn = SPI.transfer(data2);
    SPI.transfer(data1);
    delay(1);
    digitalWrite(SPI_CS, HIGH);
    SPI.endTransaction();
    if (cmdReturn != 0xFF) {
      retryCounter++;
      MY_SERIAL.println("FAILED! Retrying.");
      DACwrite(writeAddr, data2, data1);
    } else
      retryCounter = 0;
    MY_SERIAL.println("Done.");
  } else {
    MY_SERIAL.println("FAILED 3 times. Abort.");
    retryCounter = 0;
  }
}

word DACread(byte readAddr) {
  if (retryCounter < 3) {
    MY_SERIAL.print("Reading 1 byte at DAC address ");
    MY_SERIAL.print(readAddr, HEX);
    MY_SERIAL.print(" ...");
    byte cmdReturn;
    readAddr = readAddr << 3;
    byte cmdByte = readAddr + 6;
    SPI.beginTransaction(&spi_settings);
    digitalWrite(SPI_CS, LOW);
    delay(1);
    SPI.transfer(cmdByte);
    cmdReturn = SPI.transfer(0);
    word DACreply = SPI.transfer16(0);
    delay(1);
    digitalWrite(SPI_CS, HIGH);
    SPI.endTransaction();
    MY_SERIAL.print("DAC returned ");
    MY_SERIAL.println(cmdReturn, HEX);
    if (cmdReturn != 0xFF) {
      retryCounter++;
      DACread(readAddr);
    } else {
      retryCounter = 0;
      MY_SERIAL.println("Done.");
      return DACreply;
    }
  } else {
    word error = 0;
    MY_SERIAL.println("FAILED 3 times. Abort.");
    return error;
  }
}

float ofenCalcVoltage(uint8_t leistung) {  //geforderte Leistung zwischen 3 und 13 kW
  MY_SERIAL.print("Calculating analog value for ");
  MY_SERIAL.print(leistung);
  MY_SERIAL.println("kW thermal power...");
  if (leistung < 3) leistung = 3;
  if (leistung > 13) leistung = 13;
  ofenHeizleistung = leistung;  //bad programming (eventuell unterscheiden sich dann Zustand und simulierte Variable, wenn der write-Befehl dreimal scheitert)
  float voltage = ((13 - 3) / 10) * (leistung - 3);
  MY_SERIAL.print(voltage);
  MY_SERIAL.println("V");
  return voltage;
}
float voltage[3] = { 3, 6, 9 };
float lueftungCalcVoltage(uint8_t stufe) {  //LUT-artig für Lüftungsstufen
  MY_SERIAL.print("Calculating analog value for fan level");
  MY_SERIAL.print(stufe);
  MY_SERIAL.println("...");
  if (stufe < 1) lueftungSetState("off");
  if (stufe > 3) stufe = 3;
  lueftungStufe = stufe;  //bad programming (eventuell unterscheiden sich dann Zustand und simulierte Variable, wenn der write-Befehl dreimal scheitert)
  MY_SERIAL.print(voltage[stufe - 1]);
  MY_SERIAL.println("V");
  return voltage[stufe - 1];
}

void ofenSetState(char *state) {
  if (!strcmp(state, "on")) {
    MY_SERIAL.println("Setting ofen state to on...");
    digitalWrite(FET1, HIGH);
    FET1_on = true;
    DACpowerState(1, "on");
    DACsetVoltage(1, ofenCalcVoltage(ofenHeizleistung));  //Ofen schaltet auf letztem bekannten Wert ein
    ofenOn = true;
    MY_SERIAL.println("Ofen state set to on.");
  }
  if (!strcmp(state, "off")) {
    MY_SERIAL.println("Setting ofen state to off...");
    digitalWrite(FET1, LOW);
    FET1_on = false;
    DACpowerState(1, "off");
    ofenOn = false;
    MY_SERIAL.println("Ofen state set to off.");
  }
}
void lueftungSetState(char *state) {  //argument duration missing
  if (!strcmp(state, "on")) {
    MY_SERIAL.println("Setting lueftung state to on...");
    digitalWrite(FET2, HIGH);
    FET2_on = true;
    DACpowerState(2, "on");
    DACsetVoltage(2, lueftungCalcVoltage(lueftungStufe));  //Lueftung schaltet auf letztem bekannten Wert ein
    lueftungOn = true;
    MY_SERIAL.println("Lueftung state set to on.");
  }
  if (!strcmp(state, "off")) {
    MY_SERIAL.println("Setting lueftung state to off...");
    digitalWrite(FET2, LOW);
    FET2_on = false;
    DACpowerState(2, "off");
    lueftungOn = false;
    MY_SERIAL.println("Lueftung state set to off.");
  }
}

void MAX31820getAllTemperatures() {
  MY_SERIAL.println("Getting temperature data from all known MAX31820 sensors...");
  oneWire.reset();
  oneWire.skip();  //simulataneously start temperature conversion on all devices
  oneWire.write(0x44);
  delay(1000);  //wait 1000 ms, because read time slot allocation is not possible in multi-slaves queries

  for (int i = 0; i < deviceCount; i++) {
    uint8_t rom[8];
    for (int j = 0; i < 8; i++) {
      rom[j] = MAX31820addr[i][j];
    }
    oneWire.reset();
    oneWire.select(rom);
    oneWire.write(0xBE);  //read scratchpad register
    byte scratchpad[9];   //9 bit scratchpad
    for (int i = 0; i < 9; i++) {
      scratchpad[i] = oneWire.read();
    }
    if (oneWire.crc8(scratchpad, 8) == rom[7]) {
      MY_SERIAL.println("CRC match for ROM ");
      for (int i = 0; i < 8; i++) {
        MY_SERIAL.println(rom[i]);
      }
      int16_t raw = (scratchpad[1] << 8) | scratchpad[0];
      if (bitRead(raw, 15)) {
        raw = (raw ^ 0xFFFF) - 0x01;  //two's complement for negative numbers
      }

      float celsius = (float)raw / 0xF;  //last nibble 1111b = 15d = 0xF
      if (bitRead(raw, 15)) celsius = -celsius;

      switch (i) {
        case 0:
          tempAussen = celsius;
          MY_SERIAL.print("tempAussen ");
          MY_SERIAL.println(tempAussen);
          break;
        case 1:
          tempZuluft = celsius;
          MY_SERIAL.print("tempZuluft ");
          MY_SERIAL.println(tempZuluft);
          break;
        case 2:
          tempFortluft = celsius;
          MY_SERIAL.print("tempFortluft ");
          MY_SERIAL.println(tempFortluft);
          break;
        case 3:
          tempAbluft = celsius;
          MY_SERIAL.print("tempAbluft ");
          MY_SERIAL.println(tempAbluft);
          break;
        case 4: break;
      }
    }
  }
  MY_SERIAL.println("Done.");
}

void lueftungTemperatureControl() {
  float hysterese = 0.7;  // Hysterese von 1 K
  if ((tempAussen < tempFortluft - 2) && tempFortluft > tMax && tempZuluft > tMin) {
    if (abs(tempAussen - tempZuluft) < 1.5) lueftungBypassOffen = true;
  } else {
    lueftungBypassOffen = false;
  }

  if (((tempZuluft + hysterese / 2) > tempFortluft) && (lueftungBypassOffen == true)) {
    lueftungSetState("off");
  }
  if (((tempZuluft - hysterese / 2) < tempFortluft) && (lueftungBypassOffen == true)) {
    lueftungSetState("on");
  }

  if ((((tempZuluft - hysterese / 2) - tempFortluft) < -5) && (lueftungBypassOffen = false)) {
    lueftungSetState("off");
  }
  if ((((tempZuluft + hysterese / 2) - tempFortluft) > -5) && (lueftungBypassOffen = false)) {
    lueftungSetState("on");
  }
}

void checkInputs() {
  if (!digitalRead(INT_LFTG)) {
    lueftungError = true;
    digitalWrite(LED_LFTG, HIGH);
  }
}
void RTCinit() {
  MY_SERIAL.print("Initializing RTC...");
  Wire.beginTransmission(RTCaddress);
  Wire.write((uint8_t)0x23);  // Start register (timestamp_mode)
  Wire.write((uint8_t)0x6);   // TSR Register 3 First time switch to batt, TSR Register 2 Last time switch to batt
  Wire.write((uint8_t)0x00);  // 0x24 Two's complement offset value
  Wire.write((uint8_t)0x15);  // 0x25 no INV, normal offset correction mode, 24h,low-jitter mode, 6pF load caps
  Wire.write((uint8_t)0x00);  // 0x26 battery switch enabled, switch at Vth (internal ref)
  Wire.write((uint8_t)0x00);  // 0x27 Enable periodic interupt pin on INTA
  Wire.write((uint8_t)0x47);  // 0x28 INTA Clock pulse every 1 minute, RTC Mode, STOP ctl default, no CLK output
  Wire.write((uint8_t)0x40);  // 0x29 pulsed periodic interrupt
  Wire.write((uint8_t)0x00);  // 0x2a no INTB, so no interrupts configured
  Wire.endTransmission();
  MY_SERIAL.println("Done initializing RTC.");
}

void RTCgetFlags() {
  MY_SERIAL.print("Getting current RTC flag status...");
  Wire.beginTransmission(RTCaddress);
  Wire.write((uint8_t)0x02);    //stopwatch minutes register contains EMON bit
  Wire.endTransmission(false);  //RTC accepts I2C restart conditions, so the bus is not released
  Wire.requestFrom(RTCaddress, 1);
  byte emonRegister = Wire.read();
  if (bitRead(emonRegister, 7)) {  //read flags if EMON shows that flags are set
    Wire.endTransmission(false);
    Wire.beginTransmission(RTCaddress);
    Wire.write((uint8_t)0x2B);
    Wire.endTransmission(false);
    Wire.requestFrom(RTCaddress, 1);
    byte flags = Wire.read();
    Wire.endTransmission();
    MY_SERIAL.println("Done");
    if (flags != 0x00) {
      if (bitRead(flags, 5)) {
        RTCalarm1 = true;
        MY_SERIAL.println("Alarm1 RTC asserted - not implemented.");
      }
      if (bitRead(flags, 6)) {
        RTCalarm2 = true;
        MY_SERIAL.println("Alarm2 RTC asserted - not implemented.");
      }
    }
  } else {
    Wire.endTransmission();
    MY_SERIAL.println("No flags set.");
  }
}
All the output is as expected:

Code: Select all

Opened serial connection.
Initializing DAC...
Reading 1 byte at DAC address A ...DAC returned FF
Done.
Writing 30 at DAC address A ...Done.
Writing 00 at DAC address 8 ...Done.
Calculating analog value for 7kW thermal power...
4.00V
Setting wiper value of 108 for oven...
Writing 06C at DAC address 0 ...Done.
Calculating analog value for fan level2...
6.00V
Setting wiper value of 163 for lueftung...
Writing 0A3 at DAC address 1 ...Done.
Setting ofen state to off...
Writing 03 at DAC address 9 ...Done.
Ofen state set to off.
Setting lueftung state to on...
Writing 00 at DAC address 9 ...Done.
Calculating analog value for fan level2...
6.00V
Setting wiper value of 163 for lueftung...
Writing 0A3 at DAC address 1 ...Done.
Lueftung state set to on.
Done initzializing DAC.
Initializing RTC...Done initializing RTC.
Probing OneWire bus...
No more devices found.
LOOP>>>
LOOP>>>
LOOP>>>
LOOP>>>
If you change back to Serial, you will see only the beginning after the chip is rebooted and the loop output immediately - the USB driver loses the byte stream when the chip is restarted, but the duplicate data in the loop will be visible. Therefore, if you need to log sensor data while the device is running inside the loop Serial is suitable. Initial initialization is difficult to see through Serial correctly - use Serial0 for such cases together with an external adapter.
Best regards,
Alex.
Alphaprot
Posts: 4
Joined: 07 Jul 2020 15:32

Re: Serial.println() will not finish print statements

Post by Alphaprot »

Dear Alex,

thank you very much for your time and effort - especially for directly hitting me up after your vacation. What a service :)

Lacking a UART probe (I guess my TL866ii Plus does UART - but only via their crappy software and not via blurpys useful "minipro"-tool), I will likely have to use an Arduino as an UART-to-USB Bridge. Out of curiosity, what UART probe do you use?

Thank you again for your great assistance, Alex!

Best regards
Yannik

EDIT: Don't worry, I know it is a 3V3 device :)
Post Reply