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)
Related
First time ever I am doing python coding with Pyserial and RS485.
My function for reading serial data is here:
#RS485 read function
from threading import Thread
from time import sleep
def v_read_left():
b = 0
packet = bytearray()
packet.append(0x01) #
packet.append(0x03)
packet.append(0x20)
packet.append(0xab)
packet.append(0x00)
packet.append(0x02)
a = crc_find(packet)
packet += a
ser.flush()
while True:
ser.write(bytes(packet)) # write request to motor driver
sleep(0.1) # for frequency control
b = ser.read(9) # read RS485 received
#print(b)
if len(b) > 0:
print(b)
thread = Thread(target = v_read_left, args = ( ))
thread.start()
thread.join()
and the output of this function is here:
b'\x00fj\x06\x01\x03\x04\x00c'
b'\x00a\xcb\xc5\x01\x03\x04\x00h'
b'\x00b\xfa\x06\x01\x03\x04\x00`'
b'\x00`\xfa\x05\x01\x03\x04\x00^'
b'\x00c\xdb\xc8\x01\x03\x04\x00l'
b'\x00e\xfa\x05\x01\x03\x04\x00b'
b'\x00_\x1b\xd5\x01\x03\x04\x00]'
b'\x00e\xab\xca\x01\x03\x04\x00o'
b'\x00m\x0b\xc3\x01\x03\x04\x00h'
b'\x00_;\xd7\x01\x03\x04\x00`'
I am not able to identify what the problem is?
This is the BLDC motor driver RS485 command reference, I am trying to read the speed of the motor via the given example in this image.
Image
I'm trying to use pyfirmata to send and receive data between Arduino Uno R3 and my python program. At Arduino installed StandartFirmata sketch.
Code is:
from time import sleep
import serial
import pyfirmata
com_port_number = str(int(input('Введите номер COM-порта ')))
port = 'COM' + com_port_number # COM port number
print('Выбран порт COM ', port)
try:
board = pyfirmata.Arduino(port)
except serial.SerialException:
print('Не удается подключится к выбранному COM-порту')
com_port_number = str(int(input('Введите номер СОМ-порта')))
port = 'COM' + com_port_number
board = pyfirmata.Arduino(port)
sleep(1)
it = pyfirmata.util.Iterator(board)
it.start()
temp_list = []
potentiomentr = board.get_pin('a:0:o')
acid_control = board.get_pin('a:2:o')
stock_control = board.get_pin('a:3:o')
temperature_pin = board.get_pin('d:4:i') # well, this line is worked fine. Temperature sensor works correctly
in_connection_pc = board.get_pin('d:0:o') #but now i have InvalidPinDefError
triac = board.get_pin('d:6:o')
level = board.get_pin('d:8:i')
in_engine = board.get_pin('d:5:o')
in_triac = board.get_pin('d:10:o')
in_pump = board.get_pin('d:11:o')
drive_control = board.get_pin('d:12:o')
pump_control = board.get_pin('d:13:o')
while 1: # бесконечный цикл
a = temperature_pin.read()
b = in_connection_pc.write(1)
print(a)
list.append(a,b)
print(list)
sleep(3)
board.exit()
But i have some strange mistake:
Traceback (most recent call last):
File "C:/Users/lomil/PycharmProjects/Pyython_and_CSV_love/test_analog.py", line 22, in <module>
in_connection_pc = board.get_pin('d:0:i') #but now i have InvalidPinDefError??
File "C:\Users\lomil\Python_32\lib\site-packages\pyfirmata\pyfirmata.py", line 220, in get_pin
raise InvalidPinDefError('Invalid pin definition: UNAVAILABLE pin {0} at position on {1}'.format(pin_def, self.name))
pyfirmata.pyfirmata.InvalidPinDefError: Invalid pin definition: UNAVAILABLE pin d:0:i at position on COM1
When I commented all lines except
temperature_pin = board.get_pin('d:4:i')
It worked, but I can not understand what's wrong with other pins. They are totally good and worked fine when I wrote test sketch to Arduino.
The error message is actually complaining: UNAVAILABLE pin d:0:i at position on COM1. On the Arduino Uno (and most Arduinos) digital pins 0 and 1 are dual-use pins and are also used for communications over the serial port, aka COM port.
Firmata works by constantly communicating over the serial port so you can't actually use digital pins 0 and 1 for anything else while using Firmata.
So whatever wire you have plugged into your Arduino on digital pin 0, you need to move to another unused digital pin, like pin 3. So, if you move that wire to digital pin 3, then in code you would now need in_connection_pc = board.get_pin('d:3:o').
I've connected an ultrasonic distance sensor to a raspberry pi 2. When triggered the sensor is supposed to send the following 6 parameters back via serial:
frame header: 0xFF
data 1: 0x07
data 2: 0xD0
data 3: 0x01
data 4: 0x19
checksum: 0xF0
However when I'm trying to read the output I get something like this: ['\x00\xff\x01V\x00\xce']
Here are some information about the serial frame format of the sensor:
The checksum is calculated like this:
SUM =( Frame header + Data_H+ Data_L+ Temp_H+ Temp_L)&0x00FF
Note: The checksum keeps the low accumulative value of 8 bits only;
And this is the code I've written so far:
import RPi.GPIO as GPIO
import time
from serial import Serial
GPIO.setmode(GPIO.BCM) #GPIO mode
GPIO_TRIGGER = 18 #assign GPIO pins
GPIO.setup(GPIO_TRIGGER, GPIO.OUT) #direction of GPIO-Pins (IN / OUT)
data_output=[]
def uss_funct():
ser = Serial('/dev/ttyAMA0', baudrate=9600, bytesize=8, parity='N', stopbits=1)
# set trigger HIGH, sensor is waiting for falling edge
time.sleep(0.01000)
GPIO.output(GPIO_TRIGGER, True)
# set trigger LOW after 10ms -> Falling Edge
time.sleep(0.01000)
GPIO.output(GPIO_TRIGGER, False)
# set trigger back HIGH after 2ms, as LOW is supposed to be between 0.1-10ms
time.sleep(0.00200)
GPIO.output(GPIO_TRIGGER, True)
#read from rx
data_output.append(ser.read(6))
ser.close()
#clean up GPIO pins
GPIO.cleanup()
print (data_output)
if __name__ == '__main__':
uss_funct()
The checksum can be calculated quite easily, but your problem is that the data is out of sync. The first byte needs to be 0xff. Here is some code to find the front of the data (0xff), then calculate the temperature, distance and checksum:
data_output = ser.read(6)
# the first byte should be 0xff
if len(data_output) == 6 and \
data_output[0] != 0xff and 0xff in data_output:
# find where 0xff is in the data stream
still_needed = data_output.index(0xff)
# read more data, we are out of sync
data_output = data_output[still_needed:] + ser.read(still_needed)
# must get 6 bytes, and the first needs to be 0xff
if len(data_output) != 6 or data_output[0] != 0xff:
good_data = False
else:
# verify the checksum
good_data = (0 == (sum(data_output) & 0xff))
if good_data:
distance = data_output[1] * 256 + data_output[2]
temperature = data_output[3] * 256 + data_output[4]
Be sure to initialize the serial object with a timeout:
from serial import Serial
ser = Serial(..., timeout=1)
I have no way to test this, so buyer beware.
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?
I am using USB Weatherboard V3 right now.
The data is sent every 1 seconds continously from /dev/ttyUSB* ... I have tried to get the data with PySerial but I still failed.
I just can get "RESET" in the output console. I can't get the data.
What I want is output like this :
SHT15 temperature: 2.5 75.1 deg F
SHT15 humidity: 65%
SHT15 dewpoint: 62.7 deg F
BMP085 pressure: 2 2011, 10:05:235.967 in Hg FAIL
BMP085 temperature: 75.3 deg F
TEMT6000 light: 0.1%
Weather meters wind speed: speci0.0 MPH FAIL
Weather meters wind direction: -1 degrees FAIL
Weather meters rainfall: 0.00 inches FAIL
External power: 0.00 Volts FAIL
^ it come from minicom (unix serial program).
Can someone help me ?
Btw, this is my code currently :
import serial;
import io;
import time;
import os;
# Weather board script #
if __name__ == '__main__' :
try :
print '===================================\n'
print 'USB Weatherboard V3 - Python Script'
print 'Connection datasheet : '
print '(+) Port : /dev/ttyUSB0'
print '(+) Baud rate : 9600'
print '(+) Type : 8N1'
print '===================================\n'
ser = serial.Serial(port='/dev/ttyUSB0', baudrate=9600, timeout=1, xonxoff=False, rtscts=False, dsrdtr=True)
while True :
arr = ser.readlines()
for strarr in arr :
s = strarr.decode('cp1252').replace('\00','')
#s2 = s.encode('ascii');
s2 = s
if s2[1:3] != '[H' :
print s2
pass
pass
pass
except :
print 'Program exit !'
pass
finally :
ser.close()
pass
Please help me to correct it or if someone who has code it before me, please share with me :)
Weatherboard v3 datasheet : http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Weather/USB_Weather_Board_V3_datasheet_110615.pdf
Weatherboard v3 product : https://www.sparkfun.com/products/10586
arr = ser.readlines()
reads all lines from the serial device, and only then returns. Since your device is sending data ad infinitum, you should just iterate over it to get the lines while they're written, like this:
import serial
if __name__ == '__main__':
with serial.Serial(port='/dev/ttyUSB0', baudrate=9600, timeout=1,
xonxoff=False, rtscts=False, dsrdtr=True) as s:
for line in s:
print(s)