I am trying to communicate with a raspberry pi pico with my raspberry pi 4 over uart. The below code does transmit data, but I am only receiving data from the print statement.
import os
import utime
from machine import ADC
temp_sensor = ADC(4) # Default connection of temperature sensor
def temperature():
# get raw sensor data
raw_sensor_data = temp_sensor.read_u16()
# convert raw value to equivalent voltage
sensor_voltage = (raw_sensor_data / 65535)*3.3
# convert voltage to temperature (celcius)
temperature = 27. - (sensor_voltage - 0.706)/0.001721
return temperature
#print setup information :
print("OS Name : ",os.uname())
uart = machine.UART(0, baudrate = 9600)
print("UART Info : ", uart)
utime.sleep(3)
while True:
temp = temperature()
print(str(temp))
uart.write(str(temp))
utime.sleep(1)
And the code on my raspberry pi 4 is:
import serial
import time
import numpy as np
import matplotlib.pyplot as plt
#ser = serial.Serial('COM14',9600)
ser = serial.Serial('/dev/ttyACM0', 9600)
time.sleep(1)
while True:
# read two bytes of data
#data = (ser.read(8))
data = (ser.readline())
# convert bytestring to unicode transformation format -8 bit
temperature = str(data).encode("utf-8")
#print("Pico's Core Temperature : " + temperature + " Degree Celcius")
print(temperature)
The output in the terminal on my RPI 4 is:
27.2332
26.443
26.443
26.564
There is an extra new line between. If I remove print(str(temp)) from the pico code I get nothing. I can put just about anything in uart.write(str(temp)) and still receive the print statement, but without the uart.write() I will receive nothing.
extra new line: this problem is just because the print ends with new line you can change print(str(temp)) to print(str(temp), end="") in raspberry pi pico code
with respect to your second problem I don't think that uart.write(str(temp))is doing something useful. print statement is the way to send data to raspberry pi
A way I use to send data to raspberry pi is:
raspberry pi pico send the number of chars of the message then send the message
while True:
temp = temperature()
print(len(str(temp)))
utime.sleep(1)
print(str(temp))
utime.sleep(1)
the length would be between 1 and 9 so raspberry pi will receive 1 char
in raspberry pi code
while True:
# read length of data
length = int(ser.read(1).encode("utf-8"))
# read the data
data = (ser.read(length))
#convert bytestring to unicode transformation format -8 bit
temperature = str(data).encode("utf-8")
print(temperature)
I am using an accelerometer sensor in Node MCU to get 300 samples per second and store it for a week. My code below fails after some minutes.
import serial
ser = serial.Serial("COM5", 115200)
ser.flushInput()
i = 0
while True:
try:
i += 1
print (i)
ser_bytes = ser.readline()
print(ser_bytes)
except:
print("Keyboard Interrupt")
break
It failed after 4129 lines. I've attached the output
I'm sending data with Arduino through Bluetooth (jy-mcu HC-06), using this simple code:
int a;
void setup() {
Serial.begin(57600);
a = 0;
delay(2000);
}
void loop() {
Serial.println(a);
a++;
delay(40);
}
My issue is that when I try to read the data with Python (on Linux), the first 20 seconds (approx.), some data is corrupted. But after this, I can read the data correctly without any other error.
Python code:
import serial
ser = serial.Serial()
ser.port = "/dev/rfcomm0"
ser.baudrate = 57600
ser.open()
while True:
print(ser.readline())
Arduino code is a loop that sends an integer every 40ms and sums one to this integer. An example of the data corrupted:
108
109
11161831191
192
193
194
195
1111
122222222222
2220
22266
267
268
269
270
133333533333633333373
33333333344444444444444444444444444444544444444444444444491
492
493
494
I power the Arduino with an external power supply that gives 5V and 3A with a lot of stability.
I tried to read the data with an Android Bluetooth terminal app and it worked perfectly all the time. For that reason, I suppose that the error is in the Python code.
I have read a lot of information on the Internet and I have made a lot of changes in the code but nothing solves the problem. This is one of my latest codes, just to show some of my tests:
import serial, time
import sys
ser = serial.Serial()
ser.port = "/dev/rfcomm0"
ser.baudrate = 57600
ser.timeout = 1
ser.setDTR(False)
ser.setRTS(False)
ser.open()
old_data = 0
new_data = 0
ser.flushInput()
ser.flush()
ser.flushOutput()
time.sleep(1)
print("Start")
while True:
raw_data = ser.readline()
try:
ser.flushInput()
new_data = int(raw_data)
ser.flush()
except ValueError:
pass
print raw_data
if (old_data != new_data -1 and old_data != 0):
print('ERROR#####################################################')
old_data = new_data
time.sleep(0.01)
I appreciate any help, and of course, I will post here any update on this issue.
Thank you in advance!
The baudrate of bluetooth module(HC-06) is different from that of Arduino.
Try ser.baudrate = 115200 in your python code.
First time posting here so I apologize if I posted this incorrectly.
So currently I'm trying to make a digital stethoscope and plot the data live via python. I have a stethoscope with a mic shoved inside hooked up to a breadboard with the mic test circuit. This goes into an arduino which then sends the data via usb to my laptop. Currently my python code can display the incoming data live which is awesome. The problem is when I tap on the stethoscope, the incoming data should change. If I'm displaying the serial data via arduino or minicom, the data does change when I hit the stethoscope. But when I look at my python plot the data doesn't change and I can't figure out why. Here is my code;
Arduino
int sensorValue = 0; //value read from the pot
void setup() {
//init serial communications at 115200 bps;
Serial.begin(9600);
}
void loop() {
//read A0
sensorValue = analogRead(A0);
//Serial.write(sensorValue);
//Serial.print("The Voltage is: ");
Serial.println(sensorValue);
//Serial.println("V");
}
Python
import serial
import numpy as np
import matplotlib.pyplot as plt
from drawnow import *
voltArray = []
count = 0
arduinoData = serial.Serial('/dev/ttyACM0',9600)
plt.ion()
def makeFig():
plt.title('Stethascope Data')
plt.plot(voltArray,'bo-')
plt.grid(True)
plt.ylabel('Voltage (V)')
plt.ylim(0,5)
while True:
while (arduinoData.inWaiting()==0): #wait here until there is data
pass #do nothing
arduinoString = arduinoData.readline()
print arduinoString
try:
volt = float(arduinoString)
except ValueError:
# pass
print 'ValueError'
print 'Pin Value: ', volt
volt = volt*(5.0/1024.0) #arduino reads 0-5V, 10bit resolution
#2^10 = 1024, arduino outputs 0-1023
print 'Voltage: ', volt
voltArray.append(volt) #append volt value into array
drawnow(makeFig)
count = count + 1
if (count > 50):
voltArray.pop(0)
print 'End Loop'
print
Anybody have any ideas?
Currently the python program must know which port a device (Arduino) is on before Python can communicate the device.
Problem: Whenever the device is plugged out and back in, its COM port changes, so the correct serial port must be given to Python again for it to find the device.
How can Python (using pySerial) automatically search for the correct serial port to use? Is it possible for python to correctly identify the device on a serial port as an Arduino?
Use the following code to see all the available serial ports:
import serial.tools.list_ports
ports = list(serial.tools.list_ports.comports())
for p in ports:
print p
This gives me the following:
('COM4', 'Arduino Due Programming Port (COM4)', 'USB VID:PID=2341:003D SNR=75330303035351300230')
('COM11', 'RS-232 Port (COM11)', 'FTDIBUS\\VID_0856+PID_AC27+BBOPYNPPA\\0000')
To work out if it's an Arduino you could do something like:
if "Arduino" in p.description:
print "This is an Arduino!"
Using serial.tools.list_ports.comports, we can find and connect to an arduino with:
import warnings
import serial
import serial.tools.list_ports
arduino_ports = [
p.device
for p in serial.tools.list_ports.comports()
if 'Arduino' in p.description # may need tweaking to match new arduinos
]
if not arduino_ports:
raise IOError("No Arduino found")
if len(arduino_ports) > 1:
warnings.warn('Multiple Arduinos found - using the first')
ser = serial.Serial(arduino_ports[0])
If you know you're looking for exactly the same arduino each time, you can filter on p.serial_number instead
import serial.tools.list_ports
def find_arduino(serial_number):
for pinfo in serial.tools.list_ports.comports():
if pinfo.serial_number == serial_number:
return serial.Serial(pinfo.device)
raise IOError("Could not find an arduino - is it plugged in?")
ser = find_arduino(serial_number='85430353531351B09121')
"""
Written on a Windows 10 Computer, Python 2.7.9 Version.
This program automatically detects and lists ports. If no ports are found, it simply shells out. In the printout below "list(serial.tools.list_ports.comports())" finds two ports and the program lists them out - a listout shown below:
COM5 - USB-SERIAL CH340 (COM5)
Found Arduino Uno on COM5
COM4 - Microsoft USB GPS Port (COM4)
As each port is found, "CH340," (the name of the Adruino Uno) is searched for in the listed port with the "while int1 < 9:" loop. The first "If" statement looks for "CH340" and when found the integer value "int1" will be the same as the com port #. With a concatination, the operation "str1 = "COM" + str2" gives the com port name of the Adruino, eg. "COM5." The next "IF" statement looks for both "CH340" AND str1, ("COM5") in the above case. The statement "Found Arduino Uno on COM5" prints out, and "str1" is used in setting up the com port:
ser = serial.Serial(str1, 9600, timeout=10)
This program goes on to open the com port and prints data from the Adruino.
The modules "serial, sys, time, serial.tools.list_ports" must all be imported.
Written by Joseph F. Mack 01/29/2016. "A BIG Thank you" to all the individuals whose programs I "borrowed" from that are available in the many forums for Python and PYGame users!
"""
import serial
import sys
import time
import serial.tools.list_ports
serPort = ""
int1 = 0
str1 = ""
str2 = ""
# Find Live Ports
ports = list(serial.tools.list_ports.comports())
for p in ports:
print p # This causes each port's information to be printed out.
# To search this p data, use p[1].
while int1 < 9: # Loop checks "COM0" to "COM8" for Adruino Port Info.
if "CH340" in p[1]: # Looks for "CH340" in P[1].
str2 = str(int1) # Converts an Integer to a String, allowing:
str1 = "COM" + str2 # add the strings together.
if "CH340" in p[1] and str1 in p[1]: # Looks for "CH340" and "COM#"
print "Found Arduino Uno on " + str1
int1 = 9 # Causes loop to end.
if int1 == 8:
print "UNO not found!"
sys.exit() # Terminates Script.
int1 = int1 + 1
time.sleep(5) # Gives user 5 seconds to view Port information -- can be changed/removed.
# Set Port
ser = serial.Serial(str1, 9600, timeout=10) # Put in your speed and timeout value.
# This begins the opening and printout of data from the Adruino.
ser.close() # In case the port is already open this closes it.
ser.open() # Reopen the port.
ser.flushInput()
ser.flushOutput()
int1 = 0
str1 = ""
str2 = ""
while int1==0:
if "\n" not in str1: # concatinates string on one line till a line feed "\n"
str2 = ser.readline() # is found, then prints the line.
str1 += str2
print(str1)
str1=""
time.sleep(.1)
print 'serial closed'
ser.close()
Try this code (only for windows users. MAC user can withdraw idea from this concept)
import serial
import time
list=['COM1','COM2','COM3','COM4','COM5','COM6','COM7','COM8','COM9','COM10','COM11','COM12','COM13','COM14','COM15','COM16','COM17','COM18',]
COM1='COM1'
COM2='COM2'
COM3='COM3'
COM4='COM4'
COM5='COM5'
COM6='COM6'
COM7='COM7'
COM8='COM8'
COM9='COM9'
COM10='COM10'
COM11='COM11'
COM12='COM12'
COM13='COM13'
COM14='COM14'
COM15='COM15'
COM16='COM16'
COM17='COM17'
COM18='COM18'
COM19='COM19'
time.sleep(1)
ser = serial.Serial()
ser.baudrate = 9600
i=1
while True:
time.sleep(.2)
print(i)
ser.port = list[i]
try:
ser.open()
if ser.isOpen()==True:
print('connected')
#print('arduino is on COMPORT'.join(i))
break
break
except:
print('waiting')
i=i+1
if i==18:
print('Kindly remove usb cable and try again')
break
print('here we go')
while True:
print(ser.readline())