Serial connection working after reprogramming, but not after restart

Status
Not open for further replies.

fricia

Member
Hey everybody, I have the following problem: I'm working on a project where I'm reading potentionmeter values and sending them to Max as OSC messages via USB Serial (SlipSerial encoded). So far so good, the program works as expected when I upload it to my teensy 3.2. However, when the teensy is then disconnected and reconnected (i.e. restarted) the Serial connection doesn't work anymore. There is no output to Max, the Arduino Serial Monitor, or other Serial Logger software. As soon as I reupload the code it works again as expected. It seems, cutting the power somehow breaks something. Any suggestions on what I might be doing wrong?

Code:
#include <Fader.h>
#include <SLIPEncodedUSBSerial.h>

SLIPEncodedUSBSerial SLIPSerial(Serial);

const int faderAmount = 5;
const int ledPin = 13;
Fader* fader = new Fader[faderAmount];

void setup() {
  
  SLIPSerial.begin(115200);
  pinMode(ledPin, OUTPUT);
  
  fader[0].init(A0, "/fader0");
  fader[1].init(A1, "/fader1");
  fader[2].init(A2, "/fader2");
  fader[3].init(A3, "/fader3");
  fader[4].init(A4, "/fader4");

  digitalWrite(ledPin, HIGH);  
}

void loop() {

  for(int i = 0; i < faderAmount; i++)
  {
    fader[i].handleInput(SLIPSerial);
  }
}



Code:
#ifndef Fader_h
#define Fader_h

#include <Arduino.h>
#include <OSCMessage.h>
#include <SLIPEncodedUSBSerial.h>
#include <ResponsiveAnalogRead.h>



class Fader
{
  public:
    void init(int _inputPin, char* _oscAdress);
    void handleInput(SLIPEncodedUSBSerial& SLIPSerial);
  
  private:
    int inputPin;
    char* oscAdress;  
    ResponsiveAnalogRead analog {inputPin, true};
};
#endif

Code:
#include <Arduino.h>
#include <Fader.h>

void Fader::init(int _inputPin, char* _oscAdress)
{
  pinMode(_inputPin, INPUT);
  inputPin = _inputPin;
  oscAdress = _oscAdress;
  analog.setActivityThreshold(3);
  analog.enableEdgeSnap();
  analog.update(0);

  digitalWrite(13, HIGH);  
  delay(250);          
  digitalWrite(13, LOW); 
  delay(250);               
}

void Fader::handleInput(SLIPEncodedUSBSerial& SLIPSerial)
{
  analog.update();
  
  if(analog.hasChanged())
  {    
    OSCMessage msg(oscAdress);
    msg.add(analog.getValue());
    SLIPSerial.beginPacket();  
    msg.send(SLIPSerial); 
    SLIPSerial.endPacket();
  }
  else if(analog.getValue() == 1 && analog.isSleeping())
  {
    OSCMessage msg(oscAdress);
    msg.add(0);
    SLIPSerial.beginPacket();  
    msg.send(SLIPSerial); 
    SLIPSerial.endPacket();
  }
}
 
After programming other hardware comes up as a 'warm start' already powered and ready to go.

Freshly plugging it in the Teensy will be online perhaps faster than any other devices are ready.

Add a delay( 5000 ); at start of setup() and see if that changes anything. You can work that down as appropriate if it helps.
 
Thanks for the quick reply! I've seen similar suggestions in other threads and tried them already. Sadly this doesn't change anything at all.
 
No idea what the hardware is designed to do or how it works - or what might make it not work …

<edit> Millis not micros below
<edit2> on powering it should sit ~2 secs euql blink on and off - then the INITseems to do a slower toggle. On return is should do an uneven quicker blink for another ~2 secs before starting.

Along those prior lines perhaps - and not seeing what was actually tried ...:
Code:
void setup() {
  pinMode(ledPin, OUTPUT);
  while ( millis() <2500 ) {
    digitalWrite(ledPin , HIGH);  
    delay(150);          
    digitalWrite(ledPin , LOW); 
    delay(150);               
  }

  SLIPSerial.begin(115200);

  while ( millis() <5000 ) {
    digitalWrite(ledPin , HIGH);  
    delay(125);          
    digitalWrite(ledPin , LOW); 
    delay(100);               
  }

// ..
 
Last edited:
I have found the problem! It was the creation of the ResponsiveAnalogRead object. For some reason it didn't like the {} method of initialization. I moved the initialization to the constructor and now it's working.


Code:
class Fader {
  public:
    Fader(int _inputPin, char* _oscAdress);
    void handleInput(SLIPEncodedUSBSerial& SLIPSerial);
  
  private:
    int inputPin;
    char* oscAdress;  
    ResponsiveAnalogRead analog;
};

Fader::Fader(int _inputPin, char* _oscAdress) 
  : inputPin(_inputPin), oscAdress(_oscAdress), analog(_inputPin, true)
{
  pinMode(inputPin, INPUT);
  analog.setActivityThreshold(3);
  analog.enableEdgeSnap();            
}

I don't have a very deep understanding of how these things work, so I have absolutely no clue what caused the problem. But from what I understand this is the better solution anyway.
 
This might be the C++ "static initialization order fiasco" (the term to search on google...)

If your code crashes too early, in any way that impacts the USB port, your PC may not complete USB "enumeration" (basically, detecting the USB device).

The common approach used by most Arduino libs is an empty constructor, or if it has code, only initialization of member variables. Then a begin() method is used to actually do real hardware initialization and anything else beyond just initializing variables. You especially want to avoid using *any* other C++ classes from your constructor.

Even better is use of "constexpr" on your constructor (which sort-of enforces this style). This is not yet widespread practice in the Arduino world, since most boards have been using gcc 4.8 where this doesn't work. We use gcc 5.4 on Teensy 3.x, so constexpr constructors are fully supported. On top of solving these initialization problems, constexpr constructors also allow the compiler to do much more optimization of your code.
 
Status
Not open for further replies.
Back
Top