Trouble Accessing Pi's RX and TX With Serial1

Has anyone been able to successfully connect to RX and TX GPIO Pins on the RPI3 using particle-agent? I have a sensor that is connected to rx tx on the RPI but it appears that Serial1 never becomes available to my code. Been trying for two days now! Any suggestions would be greatly appreciated.


int incomingByte = 0;

void setup() {

Serial.begin(115200);
Serial1.begin(115200);
Serial.println(“Starting…”);

}

void loop() {
// send data only when you receive data:
if (Serial1.available() > 0) {
// read the incoming byte:
incomingByte = Serial1.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}


output from particle-agent serial:

Starting…


output from particle-agent logs

0000000003 system: INFO: Device xyz started
0000000003 hal: INFO: Virtual WLAN init
0000000003 system: INFO: ready():false,connecting():false,listening():false
0000000003 hal: INFO: Virtual WLAN on
0000000003 hal: INFO: Virtual WLAN connecting
0000000003 hal: INFO: Virtual WLAN connected
0000000003 hal: INFO: device key: xyz~
0000000003 hal: INFO: server key: xyz~
0000000004 system: INFO: Cloud: connecting
0000000136 system: INFO: Resolved host xxx.agent.particle.io to xxx
0000000203 system: INFO: connected to cloud xxx
0000000203 system: INFO: Cloud socket connected
0000000345 comm: INFO: Handshake: completed
0000000346 system: INFO: Cloud connected


Additional Details:
Fresh Install of Raspian
UART Flag Set in boot config
Have tried swapping rx/tx
Verified sensor is sending data over serial when particle-agent is not running
Can not read data from the sensor using the pi directly if particle-agent is running.

The support for Serial1 is not finished yet. The functions exist but are mostly empty.

I expect some issues with Serial 1 on the Raspberry Pi 3 due to baud rate issues. You probably need the core_freq=250 workaround suggested here if you have a Pi 3.

If you’d like to explore how to make it work, you can use the serial functions from the wiringPi library. It’s used internally to provide some of the functionality of the Particle on Raspberry Pi firmware so no need to add the wiringPi files to your app. See http://wiringpi.com/reference/serial-library/

Here’s a piece of untested code to get you started

#include "application.h"
// reach in to grab wiring pi header file directly
#include "/firmware/hal/src/raspberrypi/wiringPi/wiringSerial.h"

int serial;
void setup() {
  serial = serialOpen("/dev/ttyS0", 9600); // ttyAMA0 for older Pi
}

void loop() {
  serialPuts(serial, "Hello World!");
  delay(1000);
}

For others, make sure you run sudo raspi-config and enable the UART support in there, then reboot.

Thanks for the work around. Is there a list of incomplete features anywhere? The Raspberry Pi documentation made no mention that this feature wasnt complete. It could save other people a lot of time.

Thanks again.

1 Like

The best place is the firmware documentation. I’ll make sure to add a note that Serial1 is not complete.

Cool.

We were also thinking of trying a software serial on D0/D1 and use those for RX TX… do you know if that is possible?

You’d have to try it out.

My impression is that you’d occasionally have bit timing failures due to the Linux operating system pausing the firmware process. At 9600 baud, the bit time is 104 microseconds and the OS will sometimes pause the firmware for up to 50 milliseconds.

Thanks again for the quick reply Julien. I am thinking it might just make sense for me to wait for Serial1 to be implemented instead of trying these work arounds. Do you have any estimate on when we can expect that support?

Cheers,
Dave

Implementing Serial1 is going through the workarounds and figuring out all the kinks of using the UART on Linux. If you’re able to figure out the right steps for making the UART work it will speed up the implementation of Serial1.

As far as timeline I’m not able to commit to a specific time. There are a lot of areas that need work in the Pi.

I gave the following a shot…


#include "application.h"
// reach in to grab wiring pi header file directly
#include "/firmware/hal/src/raspberrypi/wiringPi/wiringSerial.h"

int serial;
void setup() {
  serial = serialOpen("/dev/ttyS0", 9600);
  Particle.publish("INFO", "Setup Complete");

}

void loop() {
  
  serialPuts(serial, "Pong!");

}

I can see the firmware flash in the console, and i can see my publish message, but my serialPut message Pong! never shows up at the particle-agent. I am running it with the serial parameter and expecting the serialPuts to show up there, correct?

thanks again

The serialPuts should do something on the TX and RX lines. Those are the wiringPi UART functions.

I used a seperate sensor and minicom to test that uart is working when particle-agent is shutdown.

after starting particle-agent, i am unable to see anything on the tx and rx lines.

Hello again everyone,
I’ve made some progress on this but i am still having the fundamental problem of not being able to get the ‘virtual’ serial port from the particle agent to interact with the physical serial on my raspberry pi, even when using the included wiringPi firmware.

If i use wiringPi’s SerialPuts function, I can send dummy data over the particle-agent serial line, my code will see it, and processes it is as expected.

Here is my lateset code:

#include "application.h"
#include "/firmware/hal/src/raspberrypi/wiringPi/wiringSerial.h"

int serial;
String sensor_data ;
char tmpStr[150];

int i, dataAvailable, currentCharacter;

void setup() {
  if ((serial = serialOpen("/dev/ttyS0", 9600)> 0)){ // ttyAMA0 for older Pi
    Particle.publish("log", "Serial Connected");

  } else  {
    Particle.publish("error", "Serial Connection Failed");
  }

}

void loop() {

 serialPuts(serial, "Dummy Temp:24.4 C");

 sensor_data="";

 //check if data available
 dataAvailable=serialDataAvail(serial);
 sprintf(tmpStr, "%i", dataAvailable);
 Particle.publish("Serial Buffer Length", tmpStr);

//if so, process it, process it
 while(serialDataAvail(serial)){

  currentCharacter = serialGetchar(serial);
  sensor_data += (char)currentCharacter;

  }
  
//if we got a sensor reading, publish it to cloud
  if(sensor_data!=""){
    Particle.publish("readSerial", sensor_data);
  }

delay(10000);
}

I’ve confirmed that serial data is being sent over ttyS0 and being read by wiringPI. It is also detected by minicom.

Here is the particle cloud processing my dummy data from putSerial.

If i remove that serialPuts line, nothing is every detected on particle-agent’s serial.

If anyone has any ideas I’d be very grateful for the feedback.

Thanks in advance.

Additonal Details:
Raspberry Pi 3

I want to make sure we're talking about the same thing.

Serial1 is the hardware serial, on pins TX and RX. Since Serial1 is not implemented yet in the firmware, you are using serialOpen and serialGetchar to interact with the hardware serial.

Serial is the virtual serial port. On a Photon, you can see that output when you connect a USB cable to your laptop. On the Raspberry Pi, you have to SSH into the Pi and do particle-agent serial. This command does not interact with hardware serial on pins TX and RX.

What does this screenshot represent? What do you mean when you say "I've confirmed that serial data is sent over ttyS0 and read by wiringPI"?

What is not happening that you expect should happen?

This topic is confusing so I'm just trying to get enough information to be able to help out.

I appreciate you sticking with me on this and taking the time to fully understand the issue.

My big picture goal for this Particle/Raspberry Pi project is to be able manage, monitor, and update fleets of the Raspberry Pi HAT I built, the PiAQ (Air Quality Sensor).

But more specifically at this moment, I am trying to get the readings from my PiAQ - which are on RX,TX of the raspberry pi read by my particle agent and displayed in particle cloud. What is not happening is I am unable to detect it in the particle code i am writing.

Does that make sense?

The screenshot of serial data was me monitoring the raspberry pi’s serial port, ttys0.

Been working on this some more this morning , using serialOpen and serialGetchar and are still unable to get readings off the hardware serial RX TX pins on the pi. Any feedback would be greatly appreciated.

Thank you.

What command did you use to monitor the ttyS0 serial port?

You can try using C++ file IO to access the serial port file directly:

#include <fstream>
using namespace std;

ifstream serialFile;
void setup() {
  serialFile.open("/dev/ttyS0");
}

void loop() {
  // read 1 character
  char c;
  serialFile >> c;
}

When i monitor ttyS0 port directly on the Pi, i can see the data coming from my pi hat no problem. I’ve used minicom, python, and c++ io and all can read ttyS0 on the Pi.

The problem is when running the code above through particle agent, the agent never detects any data on ttyS0, even though serialOpen can connect to it just fine. Do you have any serial devices you can help me test with?

Thanks.

#include "application.h"
#include "/firmware/hal/src/raspberrypi/wiringPi/wiringSerial.h"

int serial;
String sensor_data ;
char tmpStr[150];

int i, dataAvailable, currentCharacter;

void setup() {
  if ((serial = serialOpen("/dev/ttyS0", 9600)> 0)){ // ttyAMA0 for older Pi
    Particle.publish("log", "Serial Connected");

  } else  {
    Particle.publish("error", "Serial Connection Failed");
  }

}

void loop() {

 sensor_data="";

 //check if data available
 dataAvailable=serialDataAvail(serial);
 sprintf(tmpStr, "%i", dataAvailable);
 Particle.publish("Serial Buffer Length", tmpStr);

//if so, process it, process it
 while(serialDataAvail(serial)){

  currentCharacter = serialGetchar(serial);
  sensor_data += (char)currentCharacter;

  }
  
//if we got a sensor reading, publish it to cloud
  if(sensor_data!=""){
    Particle.publish("readSerial", sensor_data);
  }

delay(10000);
}

Thanks for all the investigation. I’ll take your work and keep iterating. I might not be able to get to it this week.

For my own sanity, I used a breakout board and connected my Pi Hat to a Photon and it was working great with the Serial1 code. Can’t wait to be able to do this from my Pi!


String sensorstring = "initial";

void setup() {
  Serial1.begin(115200); // open serial port 
  sensorstring.reserve(30);
  Particle.variable("sensorstring", sensorstring);
}

void loop() {
   sensorstring = Serial1.readStringUntil('\r');
   Particle.publish("sensorstring", sensorstring);
   delay(30000); // leave sensorstring up for 10 secs

 
}

2 Likes

@jvanier
Any progress on this? I would really like to be able to use Serial1 on Raspberry Pi.