Hi all,
I came across a very strange problem when using Serial communication between ESP8266 and a device measuring voltage, current and power. I've tried many things and here I briefly describe my problem and the experiments I've done. I'd appreciate any advice or help!
- About the measuring device (called "device" below)
The device ("power monitor") is an IM1281B, a module measuring current, voltage, power, frequency, ec and communicate with the MCU using UART protocol (with default baudrate 4800). The communication is simple: the MCU sends a UART command, the device does the task (e.g., measure certain quantities) and return a UART byte string consisting of the results. To show a simple example, here are some Python codes communicating with the device.
>>> from serial import Serial
>>> ser = Serial('/dev/ttyUSB0', 4800)
>>> b_command = b'\x01\x03\x00\x48\x00\x08\xc4\x1a' # the command "measure all quantities"
>>> ser.write(b_command) # send the command via serial port
>>> ser.read_all()
b'\x01\x03\x20\x00..........'
In the above code, a command is sent to the device from the serial port of the computer, and the device does what the command means, and returns the corresponding results. (It's a byte string of typical length 37.) How to interpret the returned bytes is not relevant here.
- Problem occurred when ESP8266 replaced the computer's serial port
So far so good with the computer. However, when I used the ESP8266 to send the command and receive the results, I no longer receive anything. Here are the Arduino IDE codes.
uint8_t command[8] = {0x01, 0x03, 0x00, 0x48, 0x00, 0x08, 0xC4, 0x1A}; // the command same as above
void setup()
{
Serial.begin(4800); // Serial communicates with the device
Serial1.begin(115200); // ESP8266's transmission-only port (GPIO2) used to display debugging info
Serial.println();
Serial1.println();
delay(5000); // wait a while before sending the command, to separate the command from the
// annoying boot-up gibberish of ESP8266.
}
void loop()
{
Serial.write(command, 8); // send command using UART
Serial1.println("Command sent! Waiting for reply");
while(!Serial.available()) // wait for incoming data from the device
{
Serial1.print("."); // the codes stuck in this loop
delay(500);
}
Serial1.println("\nReceived data!");
while(Serial.available()) // receive the bytes and print them to the debugging serial
{
Serial1.print(Serial.read(), HEX);
Serial1.print('\t');
}
delay(10000); // wait for 10 secs before sending another command
}
Hardware wiring:
- "TX" and "RX" pins of the ESP8266 devKit (GPIO1 and 3) connected to the device.
- GPIO2 (Serial1's TX pin) connected to the computer via a UART/USB converter, to display the debug info.
Result: After printing "Command sent! Waiting for reply", the program always got stuck in the "while(!Serial.available())" loop, and printed "......" forever.
- Is the ESP8266's boot-up gibberish responsible for this problem?
No. In the setup function, I did a 5 secs delay, and the command will be sent to the device at least 5 secs after the boot-up. The device is fully capable to invalidate and ignore the boot-up gibberish. In fact, I've used Python to simulate this "Gibberish" --> 5 secs --> command data flow, and got the response from the device. Therefore, the ESP8266's boot-up gibberish, although annoying, is not responsible for this problem.
- Did we get stuck in sending the command, or receiving the results?
To see whether the device has received the command from the device and sent out the results, I did the following:
- Connect ESP8266's TX pin to the device's RX pin.
- Connect the device's TX pin to the UART/USB converter's RX pin.
- Connect the converter's TX pin to ESP8266's RX pin.
That is, I used the computer's serial port as a UART relay. The relay codes are a simple piece of Python codes using PySerial:
from serial import Serial
ser = Serial('/dev/ttyUSB0', 4800)
while True:
x = ser.read()
ser.write(x)
print(hex(ord(x))) # print the relayed data in HEX form
Result: The computer printed the results returned by the device and, what's more, ESP8266 now can print the results, too!
The moral of the story is: The device can receive the command from ESP8266, and produce results, but ESP8266 cannot receive the results directly from the device, although it can receive the results indirectly, from the computer's serial port, with the same data, and the same baudrate 4800.
I also tries the experiment where the computer's TX (or, the UART/USB converter's TX) connects to the device's RX, and the device's TX connects to ESP8266's RX. In this way, I can send the command directly from the computer, and I'm pretty sure that the device could receive the command and respond. However, the ESP8266 could not receive anything and got stuck in the same while loop. (.......... forever)
Although I can locate the problem, I cannot understand why it was like this. Is this related to any electrical property of the serial communication? What's the difference between the data sent by the computer and by the ESP8266 chip? Any other test do you think worth doing to solve the problem?
Thanks in advance for your help!