serial input processing -> teensy4

Status
Not open for further replies.

Gius

New member
Hi All,
this is my first post and I will introduce myself: I'm a neuroscientist from united states and I've been using Arduino (manly Arduino one) for most of my scientific projects. I recently discovered the power of teensy and I decided to switch over this powerful tiny microcontroller to run my projects.
I've some got some problem of communication between processing and teensy4. From the processing side, I'm sending via serialUSB an array of int to teensy and from the teensy side (via Teensyduino) I'm reading these numbers and storing them into an array and call these variables to modify parameters in the main loop. Let me say that this code was working fine when uploaded on Arduino Uno (presumably because the reboot behavior of Arduino Uno when serial is open), but I can't get it to work on teensy. The code is working fine only the first time I send the values(array) via serialUSB to Teensy. If I try to re-send again the same or different number to teensy after the first time, it looks like teensy is not listening to the serial and not updating the array where these number are stored. the problem is the same when I try to upload and run the same code on Arduino DUE. I'm aware of the rebooting behavior of Arduino Uno and that's probably the reason why my code is working on uno but not on Due and Teensy. I did not find any workaround for this and I would really appreciate some insight on how to solve this behavior since I'm trying to convert all my previous codes to run on teensy. This Is the code I'm using on teensy:
Thank you!

Code:
#define shock_pin 20
#define CS_pin 18

int currentValue = 0;
int values[5];
int counter;

void setup() {
  Serial.begin(96000);
  pinMode(shock_pin, OUTPUT);
  pinMode(CS_pin, OUTPUT);
  pinMode(13, OUTPUT);
  digitalWrite(shock_pin, LOW);
  digitalWrite(CS_pin, LOW);

}

void protocol() {
  unsigned long a = (unsigned long) ((values[3] * 1000));
  unsigned long b = (unsigned long) ((values[1] * 1000) - a);
  digitalWrite(CS_pin, HIGH);
  delay(b);
  digitalWrite(shock_pin, HIGH);
  delay(a);
  digitalWrite(shock_pin, LOW);
  digitalWrite(CS_pin, LOW);
}

void loop() {
  if (Serial.available() > 0) {
    values[currentValue++] = Serial.read();
    if (values[0] == 1) {
      while (counter < values[4]) {
        counter ++;
        Serial.println(counter);
        protocol();
        delay((unsigned long) values[2] * 1000);
      }
    }
    else {
      counter = 0;
      values[4] = 0;
    }
  }
}

and this is the processing code:

Code:
import controlP5.*;
import processing.serial.*;

Serial port;

ControlP5 cp5;
PFont font;
Knob K1;
Knob K2;
Knob K3;
Button B;


long start = millis();
float a = 0;
boolean running = false;
float times;
float waiting = 60;

// user defined inputs
int session_lenght;
int number_of_trials;
int interval_between_trials;
int shock_duration;



void setup() {
  port = new Serial(this, "/dev/cu.usbmodem82105601", 96000);
  delay(5000);

  size(750, 600);
  cp5 = new ControlP5(this);
  font = createFont("arial", 18);

  cp5.addTextfield("Session Lenght (sec)")
    .setPosition(20, 30)
    .setSize(100, 40)
    .setFont(font)
    .setText(Integer.toString(15));

  cp5.addTextfield("Number of Trials")
    .setPosition(20, 100)
    .setSize(100, 40)
    .setFont(font)
    .setText(Integer.toString(5));

  cp5.addTextfield("Interval Between Trials (sec)")
    .setPosition(20, 170)
    .setSize(100, 40)
    .setFont(font)
    .setText(Integer.toString(60));

  cp5.addTextfield("Shock duration (sec)")
    .setPosition(20, 240)
    .setSize(100, 40)
    .setFont(font)
    .setText(Integer.toString(1));

  K1 = cp5.addKnob("knob1")
    .setPosition(45, 360)
    .setRange(0, 15)
    .setRadius(100)
    .setFont(font)
    .setColorForeground(color(220, 20, 60));

  K2 = cp5.addKnob("knob2")
    .setPosition(280, 360)
    .setRange(0, 5)
    .setRadius(100)
    .setFont(font)
    .setColorForeground(color(173, 255, 47));

  K3 = cp5.addKnob("knob3")
    .setPosition(520, 360)
    .setRange(0, 60)
    .setRadius(100)
    .setFont(font)
    .setColorForeground(color(255, 153, 51));

  B = cp5.addButton("Start")
    .setPosition(500, 100)
    .setSize(120, 70)
    .setFont(font);
}

void draw() {

  background(255, 255, 255);
  fill(0, 0, 0);
  text("Seconds trial", 85, 340);
  text("Trials", 350, 340);
  text("Seconds between trials", 515, 340);

  text("Session lenght (sec)", 130, 55);
  text("Number of trials", 130, 125);
  text("Time between trials (sec)", 130, 195);
  text("Shock duration (sec)", 130, 265);
  textSize(18);
  if (running) {
    K1.setRange(0, session_lenght);
    K2.setRange(0, number_of_trials);
    K3.setRange(0, interval_between_trials);

    B.setVisible(!cp5.isVisible());
    a = (millis() - start) / 1000.00;
    K1.setValue(a);
    if (a >= session_lenght) {
      K3.setValue(a - session_lenght);
    }
    if (times >= number_of_trials) {
      K1.setValue(a);
      if (a >= session_lenght) {
        K3.setValue(0);
        running = false;
        B.setVisible(cp5.isVisible());
      }
    }
    while (port.available() > 0) {
      String incoming = port.readStringUntil('\n');
      if (incoming != null && running) {
        incoming = trim(incoming);
        times = int(incoming);
        K2.setValue(times);
        if (a >= session_lenght) {
          start = millis();
        }
      }
    }
  }
}


void Start() {

  byte out[] = new byte[5];
  
  int value1 = (1);

  out[0] = byte(value1); 

  start = millis();
  running = true;
  
  String val1 = cp5.get(Textfield.class, "Session Lenght (sec)").getText();
  session_lenght  = Integer.parseInt(val1);
  int value2 = session_lenght;
  out[1] = byte(value2);

  String val3 = cp5.get(Textfield.class, "Interval Between Trials (sec)").getText();
  interval_between_trials = Integer.parseInt(val3);
  int value4 = interval_between_trials;
  out[2] = byte(value4);

  String val4 = cp5.get(Textfield.class, "Shock duration (sec)").getText();
  shock_duration = Integer.parseInt(val4);
  int value5 = shock_duration;
  out[3] = byte(value5);

  String val2 = cp5.get(Textfield.class, "Number of Trials").getText();
  number_of_trials = Integer.parseInt(val2);
  int value3 = number_of_trials;
  out[4] = byte(value3);

  port.write(out);
  println(out);
}
 
Last edited:
found the solution to this problem. there were different problems :D in my original sketch: first, I wasn't resetting the index of the incoming array to 0. When I did that, I was able to read the array values correctly the first time but if I updated the input values from processing, teensy was looping trough the previous once. to solve this, I had to ad a delay to slow dow the loop in order have time to update the array. Here's the modified sketch in case someone else has the same problem. I also added a void serialEvent() to read incoming values and store them into array.

Code:
#define shock_pin 20
#define CS_pin 18

int currentValue = 0;
int incomingValue = 0;
int values[5];

void setup() {
  Serial.begin(96000); // placeholder
  pinMode(shock_pin, OUTPUT);
  pinMode(CS_pin, OUTPUT);
  pinMode(13, OUTPUT);
  digitalWrite(shock_pin, LOW);
  digitalWrite(CS_pin, LOW);

}

void protocol() {
  unsigned long a = ((unsigned long) values[3] * 1000);
  unsigned long b = ((unsigned long) (values[1] * 1000) - a);
  digitalWrite(CS_pin, HIGH);
  delay(b);
  digitalWrite(shock_pin, HIGH);
  delay(a);
  digitalWrite(shock_pin, LOW);
  digitalWrite(CS_pin, LOW);
}

void loop() {
  if (values[0] == 1) {
    delay(10);
    int counter = 0;
    while (counter < values[4]) {
      counter ++;
      Serial.println(counter);
      if (counter == values[4]) {
        values[0] = 0;
        protocol();
        break;
      }
      else {
        protocol();
        delay((unsigned long) values[2] * 1000);
      }
    }
  }
}

void serialEvent() {
  if (Serial.available() > 0) {
    int incomingValue = Serial.read();
    values[currentValue] = incomingValue;
    currentValue++;
  }
  if (currentValue > 4) {
    currentValue = 0;
  }
}
 
Status
Not open for further replies.
Back
Top