Read serial data sent to mega over usb, with uno

I have an arduino mega and an uno,

The mega is running a sketch that sends and receives text strings between itself and the computer over the USB port, so i believe the serial monitor can't be used on the mega whilst USB comms is going on.

I would like to read the strings being sent between the computer and mega.
So i am using the uno to read what is being sent from and to the arduino and computer and show it on the uno's serial monitor screen on the computer.

I connected the uno's RX pin 0 to the mega's TX0 pin 1, and the uno's TX pin 1 to the mega's RX0 pin 0.

With the following sketch on the uno i can read the data that is sent from the mega to the computer, but not the other way around:

String readString;

void setup() {
  Serial.begin(115200);
}

void loop() {

  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the String readString
    delay(3);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() > 0) {
    Serial.println(readString);  //so you can see the captured String
    readString = "";
  }
}

I believe the above code reading just the TX part of the serial data from the mega to the computer?
If so, how do i make it read the RX part from the computer to the mega too?

:

The code i am running on the mega sends and receives text strings between a bus driving simulator on the computer and a real dashboard on a driving rig.

The few comments in the below code are mine, part of the reason i want to read the incoming data is to figure a few things out.

Bus Board Interface 2 code
float varlist[10];
bool prevtriglist[10];
unsigned long buff1;
unsigned long buff2;
float floatroz;
void setup() {
  Serial.begin(115200);
  Serial.setTimeout(25);

//Lights
  pinMode(47, OUTPUT);
  pinMode(48, OUTPUT);
  pinMode(49, OUTPUT);
  pinMode(50, OUTPUT);
  pinMode(51, OUTPUT);
  pinMode(52, OUTPUT);
  pinMode(53, OUTPUT);

//Switches
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);



  delay(1000);
  Serial.write("REFRESH");
  readstr();
}


void sendrequest() {
  //Serial.print("SL:0");
}

void loop() {
  
  unsigned long currentMillis = millis();

  if (currentMillis - buff1 > 2000) {
    buff1 = currentMillis;
    sendrequest();
  }
  while (Serial.available() > 0) {
    readstr();
  }
  analogWrite(47, varlist[0] * 255);
  analogWrite(48, varlist[1] * 255);
  analogWrite(49, varlist[2] * 255);
  analogWrite(50, varlist[3] * 255);
  analogWrite(51, varlist[4] * 255);
  analogWrite(52, varlist[5] * 255);
  analogWrite(53, varlist[6] * 255);

  if (currentMillis - buff2 > 500) {
    buff2 = currentMillis;
    sendfloatauto();
  }

  //      Buttons / Switches:

  if (prevtriglist[0] != !digitalRead(7)) {  // Station brake
    prevtriglist[0] = !digitalRead(7);
    sendtrig(0, prevtriglist[0]);
  }
  if (prevtriglist[1] != !digitalRead(8)) {  // Door 0
    prevtriglist[1] = !digitalRead(8);
    sendtrig(1, prevtriglist[1]);
  }
  if (prevtriglist[2] != !digitalRead(9)) {  // Door 1
    prevtriglist[2] = !digitalRead(9);
    //sendtrig(2,1);
    //delay(60);
    //sendtrig(2,0);
    sendtrig(2, prevtriglist[2]);
  }
  if (prevtriglist[3] != !digitalRead(10)) {  // High Beam
    prevtriglist[3] = !digitalRead(10);
    sendtrig(3, prevtriglist[3]);
  }
  if (prevtriglist[4] != !digitalRead(11)) {  // Kinderwagen Switch
    prevtriglist[4] = !digitalRead(11);
    sendtrig(4, prevtriglist[4]);
  }
  if (prevtriglist[5] != !digitalRead(12)) {  // Horn
    prevtriglist[5] = !digitalRead(12);
    sendtrig(5, prevtriglist[5]);
  }
}

void readstr() {
  String string1 = Serial.readStringUntil('\n');
  if (string1.substring(0, 2) == "LV") {
    int varpos = string1.indexOf(":", 3);
    int varindex = atoi(string1.substring(3, varpos).c_str());
    float varstate = atof(string1.substring(varpos + 1).c_str());
    varlist[varindex] = varstate;
  }

  if (string1.substring(0, 2) == "SV") {
    int varpos = string1.indexOf(":", 3);
    int varindex = atoi(string1.substring(3, varpos).c_str());
    float varstate = atof(string1.substring(varpos + 1).c_str());
    if (varindex == 0) {
      if (varstate == 1) {
        digitalWrite(13, HIGH);
      } else {
        digitalWrite(13, LOW);
      }
    }
  }
}

void sendtrig(int index, float var) {
  Serial.print("TV:" + String(index) + ":" + String(var));
}

void sendvar(int index, float var) {
  Serial.print("LV:" + String(index) + ":" + String(var));
}

void sendfloatauto() {
  float temp = analogRead(A0);
  temp = temp / 1024;
  temp = min(temp, 0.99);
  if (abs(temp - floatroz) > 0.05) {
    floatroz = temp;
    sendvar(5, temp);
  }
}

maybe simpler to get a USB-TTL dongle connect it to one of the Megas hardware serial ports
you can use it to receive the text from the compter
leaving the Megas USB serial port for programming and serial monitor output

i can't find my usb-ttl dongle, ordered another one tho.

Isn't there a way to do this with an uno as the usb-ttl dongle?

i can't even remember how to 'echo'? the data from the usb port on the mega to one of it's other serial ports,
did i say i was bad at programming (memory issues don't help, what i managed to do a few years ago i have to learn over again)

try this - UNO code

// UNO serial IO test using AltSoftSerial  
//
// see https://www.arduino.cc/reference/en/libraries/altsoftserial/

#include <AltSoftSerial.h>

// example connection using a UNO
// connect GND pins together
// external TTL TXD to UNO RX pin 8 (e.g. to Mega Serial1 pin 18 Tx1)
// external TTL RXD to UNO TX pin 9 (e.e. to Mega Serial1 pin 19 RX1)

AltSoftSerial altSerial;

void setup() {
  Serial.begin(115200);
  Serial.println("AltSoftSerial test");
  //Begin serial communication with Arduino and external device
  altSerial.begin(38400);
}

void loop() {
  // check serial monitor input transmit to external TTL
  if (Serial.available()) {
    char command = Serial.read();
    //Serial.println(command);
    altSerial.print(command);
  }
  // check external TTL transmit to serial monitor
  while (altSerial.available()) {
    char reponse = altSerial.read();
    Serial.print(reponse);
  }
}

Mega code

// Arduino Mega serial1 test

// mega Serial1 pin 18 is Tx
//      Serial1 pin 19 is Rx
// for loopback test connect pin 18 to pin 19

// for RS232 shield connect pin 18 to Tx and pin 19 to Rx
// for loopback test connect 9 pin D connector pins 2 and 3
// connect GND pins together

void setup() {
  Serial.begin(115200);   // initialise serial monitor port
  Serial1.begin(38400);//115200);  // initialise Serial1
  Serial.write("Arduino Mega Serial1 test -  for loopback test connect pin 18 to pin 19\n");
}

void loop() {
  if (Serial1.available()) {      // read from Serial1 output to Serial
    Serial.write(Serial1.read());
  }
  if (Serial.available()) {       // read from Serial outut to Serial1
    char inByte = Serial.read();
    //Serial.write(inByte);     // local echo if required
    Serial1.write(inByte);
  }
}

connect UNO RX pin 8 to mega Serial1TX pin 18
UNO TX pin 9 to mega Serial1 RX pin 19

Your baud rate is way too high to allow software serial on the Uno, so you've only one serial port, and that's used for Serial Monitor - that's what you're sending your prints to. Oops!

You need an app running on the PC that can listen to two serial ports in real time, and display the traffic on the PC. These apps are out there. You'll need two serial-USB adapters.
Keywords for Google - "Serial port sniffing application".

To me, the only other way would be to use a second Arduino with three serial - two RX ports for listening to the traffic, and one UART for sending to Serial Monitor; write a small sketch that receives from the two streams, tags each with port# and timestamp, and merge the streams to the Serial Monitor.

But the PC apps are tremendous, you won't regret looking at them just for the understanding that they're out there.

1 Like

ahhh, so is 115200 baud too fast?
i did try turning it upto 500000 baud (so would have had no chance of using an uno then)
the sketch running on the mega is reading (and sending) data to a game via a .dll, but it only sends data when something changes, rather than a constant stream of data as other sketches/.dll's do.

So i am noticing slight delays in the led's reacting to the in game dashboard lights, most noticeable with the indicator light (turn signals)
So i tried an even faster baud rate, but soon learnt that i can't do much about the delays...

...well, if i knew how to program i maybe could, as the source code is posted for this .dll, but i struggle with arduino coding, so it was as much as i could manage to build the provided solution in visual studio.

Anyway, back to my original question, i've just received 2 x TTL - USB dongles,
and i have extra arduino mega's, a due, and a few pro micro's.

I'll try reading the data from the mega with the TTL-usb dongles first, using the code above on the mega 'Arduino Mega serail1 test'

thinking about it, i really only want to listen in to the data that is sent from the pc to the arduino, so i should have been able to do that by plugging the uno's RX pin into the RX pin of the mega instead of the TX pin?

Yes, carefully. The RX pin of the Uno is driven by the USB-serial chip on your Uno, as well as being accessible on the RX pin. (Go to the Arduino.cc website, look up the published schematic PDF for the Uno) Yes, you can receive on that pin, and then reflect what is received back out to Serial Monitor. What you send will also appear on the TX pin of the Uno, so do not connect that to the Mega. Please remember to connect the grounds of the Mega and the Uno, as that is essential.

Yes. I know CoolTerm lets you open multiple windows for listening, I suspect another well-known terminal emulator PuTTY would also.

The apps for specifically observing two way serial traffic go the extra step of showing the two sides together and can provide time stamps so you see who said what to whom when.

a7

1 Like

Thankyou everyone for your help.

i've downloaded PuTTY,
Connected one of my TTL-USB dongles RX pin to the mega's TX0 pin, and the other TTL dongle i connected it's RX pin to the megas RX0 pin... the ones the USB is talking to the arduino through.

And i can see the data being sent both ways,

I know i really should do this by echoing the data from serial0 to serial 1 and vice versa, and connecting the TTL dongles to serial 1 (and perhaps serial 2)

But by 'sniffing' the data from serial0 i've managed to read what i needed... the data from the game to the arduino is strings of text with a newline delimiter (i think it's called)

and the data is:
$V:0:Nordspitze
$V:0:Bauernhof

That is what is shown in the buses interior 'next stop' display, 2 words alternating every couple of seconds for longer stop names,

I believe the $V bit means it's a string value, the 0 means it's the first in the list of 'stringvars' in the .opl file, and the last text is what is to be displayed on the LCD.

I now need to figure out how to read that string value starting with $V, and send it to an LCD.

1 Like

No, I'm with you the way you did it. Think of it as "minimally invasive", no changes to any code you working with, just pure spying.

Anyway, nice work.

a7

1 Like

Hi,

interested in the details of this sketch, can you post your sketch and connection details..?

I am making a motorized injection machine, Precious Plastic style, but with Nema & Arduino...

I am trying to access RS232 on an external LCDA86G Stepper Driver with Encoder to obtain live positioning data, and hopefully live current data, as the Lichuan app that I have seems to show that it should be configured actually at only 40% of max allowed current before it gives an over-current error - on the error, have to reset the driver, losing steps, so am hoping to also keep power to the encoder board, reset the driver via a relay, and then be able to recuperate the position and keep going in the sketch with real position data... and whilst connected, from the app change over-current limit to 80%, so I can get twice the power, closer to what my original calculations for this machine should have before buying this setup...
To do all this I am going to try use the Arduino as a USB-RS232 passthrough (via MAX232 board), as I want to try to print to serial the commands that the Lichuan app uses to communicate with the driver to get the encoder and current data..

First will try removing IC from an UNO, just to try min working config, see if app can connect, if yes, then try with PuTTY or other to see if can see any data that way, then would like to add a sketch with the Arduino getting involved, as finally would like the Arduino to be able to get and react to this data...

I have available a Nano which I am presently using to send motor movements, get endstops, temp, etc, also have an UNO, and I think a Mega somewhere (have to check is functional!).. if this can be done via NewSoftSerial during testing, or should be done with2 HW serial (Mega), I am open, however final sketch (once discovered the useful commands for sketch) will be Serial reporting via UART to an ESP32 with Touch Display all NextInjection parameters to return the parameters sent by the user as a LastCheck before the Nano proceeds with the injection (blocking only interruptible by EmergencyStop interrupt, but is generally so fast, a second or 2 at most, that once confirmed there will no time to stop, unless driver over-currents and resets, so want to be able to monitor between driver and Nano to keep current below this threshold)

Sorry if too much info, or if in wrong place, ATM am trying to get access to the RS232 to be able to develop options for sketches, but also am looking for people who would like to help develop this further... self-employed, have to work half the week, other work obligations cropping up, etc, etc! which I could divide myself by 4!
have several years experience with Arduino, would consider myself capable learner but certainly not a pro! always interested in exploring the multiple options to do things, ATM getting used to functions and trying to organise this sketch into tabs, let the Nano just be the motor controller, and the ESP32 do all the buttons and parameter changes, be able to store successful injections (have about 6-8 different moulds ATM, each distinct volumen, some requiere much more pressure to fill, etc..)

anyway, times up says my pomodoro! :wink:

Cheers!
Andy
:slight_smile:

sounds like the Mega with its multiple hardware serial ports would be a good start

an update:

got my mega running and configured for 2 serial connections and connect to the driver from both arduino and PC, and could also run the PC app to access driver parameters, but came across another issue that will make me take a completely different course now..

the actual closed loop driver is deciding on its on the max current (measured with ACS712) to send to the motor, and in the moment of the plunger reaching the plastic, it seems to be maxing out at 3A (giving an over current error), instead of the 6A that the manual indicates... so injection is stopped... at lower speeds can get the mould to fill, and then it errors at less, about 2-2.5A, so cannot maintain the extra hold pressure after filled to get a good finish... when testing with switch 5 in NO-ENCODER, then I can continually force the motor (with a LOT of missed steps), and higher speeds miss more steps so plunger advances less, lower speeds plunger advances more but obviously slower means plastic cools before mould is full - there is a sweet spot where the plunger will go the fastest, with a load of missed steps sounding, but is still slower than the WITH ENCODER speeds, and critically, the amps during this type of use do not pass almost ever 1A, so very low compared to driver max...

don't understand why and don't see any options via the available parameters that could change to affect this behaviour (although some of the chinese to english translated parameter names are incomprensible and cannot find their meaning on the web), so am going to go for plan B:

get a simpler 7.2A driver with no encoder input, set it at max amps, then take the A+, A-, B+, B- encoder data straight to the Arduino and try and read that info direct and integrate with the motor info... my aim here is that when motor starts to report lost steps with respect to the sent steps, then I know that the mould is full, so can use this step lapse (maybe define a % loss at which point stop this programmed move, not sure yet) to change to another state, where I can apply a slower speed and hold it for the time needed to give the holding pressure needed to properly finish the injection after filling, which assures a much cleaner smooth surface on the parts, before finally moving back a small amount to release the mould..

As I should be able to previsible use the lost steps between sent and realised to detect the mouldFull situation, hopefully this will resolve what I need to do, whilst the driver using the full 7.2A and not varying when it decides that it wants to (understand perfectly that this type of closed loop driver control may be very useful for other situations, but for my use case it is playing havoc with my intentions to observe the current and steps necessary to fill any mould I need to... )...

I really do not need to know absolute steps and position over multiple injections, as I will also be refilling the barrel with new plastic after each injection (so it has time to heat up before reaching nozzle and keep up continuous production) so each time I start a new injection cycle (with a purge to mark when new hot plastic starts to come out the nozzle) will be a zeroing..

wish me luck, I don't choose the easy things to try out, any advice on my self-learning journey is appreciated, and all options are considered and weighed their advantages, etc with my steppered (pun intended) knowledge about Arduino, steppers and motors :wink:

Cheers!

Andy
:slight_smile:

PD I have seen varios posts by @Robin2 that I am trying to take on board, would like your opinion as, as always, there is so much info out there that at my level is hard to decipher what is more applicable to me at this moment.. I am using FastAccelStepper, and my hope is to read encoder pins each loop() to detect a state change (I don't think I will be using the motor at more than 2000steps/s, 5rps, of a max 10000 of the motor, encoder is 1000ppr, so max 5000pps, A & B, so x4 = 20000 state changes per second that may have to detect...) not sure how that will affect my Nano/Uno just yet, still have to add a few more bits and pieces to the loop(), but the Nano will only be controlling the actual motor move, whilst a ESP32 display will send the full nextInjection parameter set before each move, and the move should be the only thing the Nano is doing while !EmergancyStopActive, but should not be blocking.. still learning thou :wink:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.