Go Down

Topic: bi-directional serial communication (Arduino Uno, Feather Huzzah (ESP8266)) (Read 364 times) previous topic - next topic

asclark109

Hi there, new to arduinos.

I have a project whereby 6x MAX6675 collect temperature data that's "bused" back to the Arduino Uno. Then, those 6x data points should be sent from the Arduino Uno to the feather Huzzah (ESP8266) using serial communication (Software Serial). The feather Huzzah sends that data over wifi to Adafruit io. Then, I want the feather to send back a message equivalent to "successfully sent to storage". Therefore, a message has to be sent, and a message has to be received back. Meanwhile, there is an LCD display that gives updates. To get help on this portion, I am breaking down the problem to just figuring out the arduino<-->huzzah serial communication.

I get no response back from the feather Huzzah when running my code and circuit.

connections:
(Arduino <--> to Huzzah)
pin 2 (denoted as Rx via Software Serial) <--> Tx (huzzah)
pin 3 (denoted as Tx via Software Serial) <--> 2x resistors to get ~3.3V <--> Rx (huzzah)
GND <--> GND <--> GND (huzzah)

Huzzah is power sourced from micro-USB plugged into wall outlet. hopefully, powering the huzzah (ESP8266) with the USB does not render the TX/RX pins unavailable. If so, then Software Serial needs to be used for the Huzzah as well.

I added serial print statements to help debug, and again it appears I'm not getting something back from the Huzzah.

Arduino Code
Code: [Select]
//LCD Display
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);

//Serial communications with Huzzah (ESP8266)
#include <SoftwareSerial.h>
SoftwareSerial espSerial(2, 3);  //RX, TX
String msg;
String response;

void setup(){
  //start serial communication with computer
  Serial.begin(9600);
 
  //start serial communications with Huzzah (ESP8266)
  espSerial.begin(9600);
 
  //start up LCD
  //set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  //print a message to the LCD.
  lcd.clear();
  lcd.print("startup comms...");
  delay(2000); 
  lcd.clear(); 
}

void loop(){
  //collect data
  lcd.print("collecting..");
  lcd.setCursor(0,1);
  float h = 100;
  float t = 23;

  //send data to serial monitor
  Serial.print("H: ");
  Serial.print(h);
  Serial.print(", ");
  Serial.print("T: ");
  Serial.print(t);
  Serial.println(" C");

  //send data to huzzah via software serial
  msg = String("from arduino: ")+String("H= ")+String(h)+String("T= ")+String(t);
  espSerial.println(msg);
  Serial.println("data sent from arduino to huzzah");

  //wait for huzzah to process information send something back
  Serial.println("wait");
  delay(30);

  //print out response from Huzzah
  if (espSerial.available() > 0) {
    response = espSerial.readString();
    Serial.print("I received from huzzah: ");
    Serial.println(response);
    // update LCD
    lcd.setCursor(0,1);
    lcd.print("sent to cloud!");
  }
  else {
    Serial.println("no response from huz");
    lcd.print("no response");
  }
  delay(1000);
  lcd.clear();
}


Huzzah (ESP8266) Code
Code: [Select]
void setup() {
    Serial.begin(9600);
}

void loop() {
    String content = "";
    char character;

    while (Serial.available()) {
       character = Serial.read();
       content.concat(character);
    }

    if (content != "") {
        Serial.write("g");
        delay(30);
    }
}



Serial Output:
"H: 100.00, T: 23.00 C
data sent from arduino to huzzah
wait
no response from huz
H: 100.00, T: 23.00 C
data sent from arduino to huzzah
wait
no response from huz
...


It appears my Huzzah is not doing much. Thank you, and I apologize because this topic probably comes up often with noobs.

Koepel

Sorry for the long reply, it turned out to be longer than I thought. I hope it is helpful. By the way, the answer is "yes", try SoftwareSerial on the Huzzah.

A few notes:

The ESP32 has an extra serial port.

For the ESP8266 there is a way to send debug messages to the serial output, and use the real hardware serial port for something else. I think that TX of the second serial port is used via a bypass resistor to get it into the usb-serial chip. I can't find it right now, but I can try to look for it if you want.

Both the ESP32 and the ESP8266 are 3.3V boards and the Arduino Uno is a 5V board.
The MAX6675 works with 3.3V and 5V.
The ESP8266 is more or less 5V tolerant on its pins, but the ESP32 is not !

SoftwareSerial is the very last option. It will put a lot of stress on the Arduino Uno and some things might no longer work. I read that SoftwareSerial on the ESP8266 is not so bad.

I noticed that your LCD display is not a I2C LCD display, so you have a LCD display connected to the Uno with all those wires.

How to get into trouble

The least trouble is when everything runs at the same voltage and without SoftwareSerial and preferrably everything with a single Arduino or Arduino-compatible board.
The maximum trouble is combining 3.3V with 5V and using SoftwareSerial and multiple boards. That is what you have :o

A few solutions

1. Run everything on a ESP32 and connect the MAX6675 to the ESP32 and use a 3.3V display. I don't know if the MAX6675 or its library will run on a ESP32. The display could be an intelligent display such as a Nextion. Using a Nextion display requires a lot of time to learn how to use it.

2. If you have most things already working (Uno with MAX6675 and Huzzah with Adafruit IO), then you only need a good solution for the communication.
It is allowed to connect Uno-TX to Huzzah-RX without resistors, since the ESP8266 is more or less 5V tolerant. However, when one of them can be powered down, then I suggest a safety resistor in the signal line of 1k.
The Huzzah-TX has only 3.3V high level. That is "enough" for the Uno-RX. It is not ideal, but it is enough. If the wires are short, then you can try it. I would add a safety resistor of 1k in the signal line here as well. You could use a "level shifter".
Connecting the Arduino Uno to the Huzzah and also connect it to the usb-serial to computer should be avoided.

In the schematic is a resistor R11 of 1k between the usb-serial chip and the ESP8266. That means you can override the signal with a strong signal at the RXD pin.
For a strong signal, you should not use resistors to lower the voltage and you should not use that safety resistor.
If you connect the Uno-TX directly to the Huzzah-RX then you have a strong signal, but the Uno will push 5V via R11 of 1k into the usb-serial chip. I don't know if the usb-serial chip likes that.

The option with the bypass-resistor does not push 5V into the usb-serial chip.
Using SoftwareSerial on the Huzzah will also be safe and will not push 5V into the usb-serial chip. Use other pins than RX and TX. I suggest 1k safety resistors in the signal line, and everything should be fine 8)

Tests

When something is not working, then you should make a small test sketch. Experienced software engineers test every part on its own before combining it. So you should do that as well. Don't make the end result and then try to fix problems. Make your project step by step.
You can make a sketch that sends every second a message to the other one, and then try to receive that with the smallest possible sketch.

PerryBebbington

Hello asclark109,
In addition to the excellent advice from Koepel:

I don't have a Feather Huzzah but I do have other ESP8266 boards.

Software serial does not work well on an ESP8266 because the interrupts needed for WiFi mess up the timings for a software serial port.

If you don't mind losing the USB port you can get at the first serial port using Serial.swap() like this:
Code: [Select]
void setup_serial_port() {
  uint32_t baudrate = 57600;  // Put in here the baud rate you want
  Serial.begin(baudrate);
  Serial.swap();             // Moves the serial port on to GPIO13 Rx, GPIO15 Tx
}

Have a look at Robin's excellent Serial input basics

[EDIT]
If you are using GPIO15 as Tx you might also need a pull down resistor on GPIO15 as this pin being high on start up changes the way it starts up (something to do with external flash I think, not sure). I have found 3k3 works fine.

Koepel

Software serial does not work well on an ESP8266 because the interrupts needed for WiFi mess up the timings for a software serial port.
I didn't know that. Good to know. Thanks.

When using Serial.swap(), then the bypass resistor is not far way ;)

A bypass resistor of 1k between GPI01 (D10) en GPI02 (D4) will enable debug output with Serial1.println(). Not "Serial", but "Serial1" and only TX.
I think the Serial.swap() should be called after the Serial.begin(). Then the "Serial" port is at pin GPIO13 (D7=RX) en GPIO15 (D8=TX). At startup the swap has not been done yet, so uploading a sketch is possible.

An alternative is not using the usb-serial, but OTA (upload sketch via Wifi).
Debug messages can be shown (via Wifi) with telnet: https://www.youtube.com/watch?v=1pwqS_NUG7Q.

asclark109

Okay, I have quite a few things to learn (maybe I should have added I'm new to electronics :D). Both responses were very helpful. I downloaded Fritzing to facilitate conversation. You will laugh at me labeling one resistor as 1 kohm--the other is 2 kohm (and I can't interpret resistor labeling easily), but I've tried to be a good boy and use appropriate color wiring.

How to get into trouble

The least trouble is when everything runs at the same voltage and without SoftwareSerial and preferrably everything with a single Arduino or Arduino-compatible board.
The maximum trouble is combining 3.3V with 5V and using SoftwareSerial and multiple boards. That is what you have :o

A few solutions
...Connecting the Arduino Uno to the Huzzah and also connect it to the usb-serial to computer should be avoided.
I've attached some photos. Correct, display is using 6 GPIO pins of the arduino. I didn't emphasize enough, but you're right about solving the small problems first. Separately, I got the 6x MAX6675 working with the arduino, then (separately) I got the screen working with the arduino, and then (separately) I got the arduino talking with the Huzzah (but I think I was mistaken about it working). I think I will regress to a very small working script--and reference the serial communication tutorial (thank you, PerryBebbington)

I worried about the number of arduino pins getting used, but I read that I can use the pins on the "analog in" side as GPIO pins for the MAX6675 modules that people frequently plug into the "digital" side.

If you don't mind losing the USB port you can get at the first serial port using Serial.swap()
...
[EDIT]
If you are using GPIO15 as Tx you might also need a pull down resistor on GPIO15 as this pin being high on start up changes the way it starts up (something to do with external flash I think, not sure). I have found 3k3 works fine.
Okay, so as I understand it, I can use Serial.swap(), in which case I would re-route the wires currently connected to RX,TX to 13,15 respectively. You point out that I should use a pull-down resistor when using GPIO 15 as TX--so, I should add a 3k3 resistor between that line and ground. My understanding is that the pins output a 3.3 V signal out already--but I presume the purpose of the pulldown is to make sure it starts-up properly?






PerryBebbington

That's neat!
You will probably find WiFi doesn't work with it in the  middle of the breadboard like that. Having the aerial that close to the breadboard contact stripes interferes with it, or at least it did for mine. Use header pins to lift it off the board and have the aerial hanging over the edge.

I had problems with mine not starting up sometimes, also it seemed to be affected by my hand being close to it, which suggested a floating input. After lots of reading I discovered the need to pull GPIO15 down, once I did that the problems stopped.

Koepel

The website randomnerdtutorials was very helpful for me to start with ESP8266 and ESP32. This page has a table with notes about the startup conditions for the pins: https://randomnerdtutorials.com/esp8266-pinout-reference-gpios/.

Every analog pin on the Arduino Uno is also a digital pin. You can use pin "A0" in same way as for example pin "8".
Pin A4 and A5 are the I2C bus.

There is always more to learn. Did you know that the potentiometer for the display does not really need to vary between GND and 5V ? The display has an internal resistor and only a variable resistor between GND and the display pin is needed.

We don't use the String object in simple basic Arduino boards such as the Uno. The String object is allocated from the heap, and it can cause the "kaboom" scenario: https://learn.adafruit.com/memories-of-an-arduino/optimizing-sram.

The way you have written the text of the sketch and wired the breadboard shows that you make things good and organized. That's the main thing you need to be a programmer 8) However, your indent is 2 spaces for the Uno and 4 spaces for the ESP8266 :o

asclark109

Thank you both for the helpfulness. I re-wired the RX/TX connections on the ESP8266 to 13,15 (see image attachment) as per Perry's advice to use Serial.swap() .

It took me all day to work out the serial communications. I followed the pinned post on serial connections for beginners, and I restructured my code to have the arduino send data in the form <23.25,26.00,...> to the ESP8266. Then, ESP8266, unpacks and parses the string into 6 floats and sends those 6 floats to adafruit io. It sends back a single character "g" to confirm success to the arduino. However, adafruit io limits the upload speed for the service to 60 datapoints per minute (uploading 6 floats at a time means the ESP8266 is bottle-necked into only being able to handle uploading once every 10 seconds at maximum). So, for now, I am having the arduino keep a timer: collect data as fast as you would like; send data over to the ESP8266 whenever ~13 seconds have elapsed since the last time data was sent to the ESP8266. If the ESP8266 uploads more than 60 datapoints per minute, I am hit with a "throttling limit" warning, and if that continues the data feed can get completely "kicked". To preserve the "missing data", I will have all the data the arduino receive also transmit it over serial to the computer where it can be logged with Putty (a desktop app that will save serial monitor output).

The project is to take temperature readings of a pork roast at various radial depths as it cooks (I have food-safe k-type thermocouple probes rated to high heat environments). Then, I'll try to process that temperature profile data and compare it to that expected from using the Heat equation (I found some literature on the thermo-physical properties of meat). I am also going to see if I can do "in-situ" forward prediction of the temperature profile in time based on the current temperature profile (for instance: "what will the temperature profile look like 5 minutes from now given the current profile?"--or "how much longer should the meat be cooked at current conditions to reach an internal temperature of 150F?" ). I am an early-career chemical engineer, and I think it would be so cool to manage to do this (it would be really relevant to my work).

However, your indent is 2 spaces for the Uno and 4 spaces for the ESP8266 :o
Good point. I noticed that and made the change! Since earlier today, I edited the code quite a bit, following your advice.




PerryBebbington

In your diagram in reply #7 there is no pull down resistor on GPIO15. If it works OK then fine, if you have problems with it starting this will be the reason.

You have no power to the Feather.

Is it now doing what you want?

asclark109

No pull down resister added yet (ordered a resistor variety pack including 3k3 because the kit I got doesn't have them). I could add a couple of resistors in series with why I have (1 k + 2 k + 220 ohm = 3k22 ohm), but perhaps that's "ugly".

Something strange does appear to happen on start-up based on the serial output of the arduino, but it appears to work fine otherwise.

Right now, I externally power the feather through the microUSB. It would be easier to power it with the arduino 5V line, but it will require a "5 V terminal to USB" based on the power management article for the feather (https://www.adafruit.com/product/3972). it says to expect up to 250 mA of drawn current. I read arduinos shouldn't be taken up to 400-500 mA drawn. The Data sheets of these other parts I have show low current draw, but I am nervous about frying the arduino somehow by having so many things "hooked up" to it--so I am keeping the power supply separate from the arduino's.

PerryBebbington

Quote
No pull down resister added yet (ordered a resistor variety pack including 3k3 because the kit I got doesn't have them). I could add a couple of resistors in series with why I have (1 k + 2 k + 220 ohm = 3k22 ohm), but perhaps that's "ugly".
The exact value does not matter, if you have a 2k resistor use that. If not having it does not cause a problem don't worry about it, but the symptoms of needing the resistor is that it randomly fails to start up with no obvious reason.

What are you powering the Arduino from? If from anything other than 5V don't use it to power the feather. If from USB you should be OK to power the feather from the 5V pin on the Arduino BUT please use a capacitor of at least 220μF (bigger is better, within reason) across the supply physically close to the feather to smooth out the current surges when it transmits.

Go Up