I am wondering is there any way to run python script via Arduino commands in Windows ?
I don't know if this answers your question, but you can download Vpython library to create some cool projects with it, or connect sensors and getting data back into python from arduino or viceversa
So for example:
int trigPin=13; //Sensor Trig pin connected to Arduino pin 13
int echoPin=11; //Sensor Echo pin connected to Arduino pin 11
float pingTime; //time for ping to travel from sensor to target and return
float targetDistance; //Distance to Target in inches
float speedOfSound=776.5; //Speed of sound in miles per hour when temp is 77 degrees.
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(trigPin, LOW); //Set trigger pin low
delayMicroseconds(2000); //Let signal settle
digitalWrite(trigPin, HIGH); //Set trigPin high
delayMicroseconds(15); //Delay in high state
digitalWrite(trigPin, LOW); //ping has now been sent
delayMicroseconds(10); //Delay in low state
pingTime = pulseIn(echoPin, HIGH); //pingTime is presented in microceconds
pingTime=pingTime/1000000; //convert pingTime to seconds by dividing by 1000000 (microseconds in a second)
pingTime=pingTime/3600; //convert pingtime to hourse by dividing by 3600 (seconds in an hour)
targetDistance= speedOfSound * pingTime; //This will be in miles, since speed of sound was miles per hour
targetDistance=targetDistance/2; //Remember ping travels to target and back from target, so you must divide by 2 for actual target distance.
targetDistance= targetDistance*63360; //Convert miles to inches by multipling by 63360 (inches per mile)
Serial.println(targetDistance);
delay(100); //delay tenth of a second to slow things down a little.
}
And in python
import serial #Import Serial Library
from visual import * #Import all the vPython library
arduinoSerialData = serial.Serial('com11', 9600) #Create an object for the Serial port. Adjust 'com11' to whatever port your arduino is sending to.
measuringRod = cylinder( radius= .1, length=6, color=color.yellow, pos=(-3,-2,0))
lengthLabel = label(pos=(0,5,0), text='Target Distance is: ', box=false, height=30)
target=box(pos=(0,-.5,0), length=.2, width=3, height=3, color=color.green)
while (1==1): #Create a loop that continues to read and display the data
rate(20)#Tell vpython to run this loop 20 times a second
if (arduinoSerialData.inWaiting()>0): #Check to see if a data point is available on the serial port
myData = arduinoSerialData.readline() #Read the distance measure as a string
print myData #Print the measurement to confirm things are working
distance = float(myData) #convert reading to a floating point number
measuringRod.length=distance #Change the length of your measuring rod to your last measurement
target.pos=(-3+distance,-.5,0)
myLabel= 'Target Distance is: ' + myData #Create label by appending string myData to string
lengthLabel.text = myLabel #display updated myLabel on your graphic
This will make graphics in python representing something you are holding in front of an ultrasonic sensor and you can see the object moving in real time
I took the code from this website:
Toptechboy
This is has really good tutorial how to hook up arduino to python! And is very simple
I believe that there won't be any Arduino library that support Python because python is interpreted and the Arduino doesn't have the memory for the entire of Python, if you're looking to program an Arduino using Python then maybe just try C the code you need to learn for programming the Arduino isn't too different to the code you would find in python most of the code you can find here :
https://www.arduino.cc/en/Reference/HomePage
but these are some of the python modules related to running Python on an Arduino : http://playground.arduino.cc/CommonTopics/PyMite
Related
I'm using LoRa Dorji DRF1278DM as a communication module and set it central mode. From the datasheet (http://www.dorji.com/docs/data/DRF1278DM.pdf), the central module needs to send a string with a specific format.
I'm using raspberry pi for the central module and arduino for the node module (with node id=1). Trying a simple program, to send string "hello" from Raspberry to Arduino. This is the code:
import serial
if __name__ == '__main__':
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
ser.flush()
while True:
ser.write(serial.to_bytes([0x00,0x01,0x68,0x65,0x6c,0x6c,0x6f]))
time.sleep(5)
*2 first bytes for the id node and the rest is 'hello' in hex
Arduino receive data from the raspberry but have a problem to receive it in string type
void setup(){
Serial.begin(9600);
}
int=data;
void loop(){
if(Serial.available()>0){
data=Serial.read();
Serial.println(data);}
}
If I set the data type as integer, there isn't any problem in receiving it but don't know how to convert it to "hello" back. Try set data type as char but giving error "incmompatible types in assignment of 'int' to 'char'
Is there a way to receive it as string? also is there other method that allow me to send data from raspberry pi without converting each data as hex and then send it in bytes with keep including the header bytes(node id of node module)
I am having some problems getting my Raspberry Pi 4 and Arduino uno to communicate successfully using nRF24L01+ wireless modules.
I have tried several different youtube tutorials and this the 3rd time i've come back to this project only to be met with failure.
For the arduino I am using the TMRH20 RF24 library
The tutorial I have most recently followed is this one.
The code used in the tutorial for the arduino is a basic transmit only code:
#include<RF24.h>
//ce,csn pins
RF24 radio(9,10);
void setup() {
Serial.begin(9600);
radio.begin();
radio.setPALevel(RF24_PA_MAX);
radio.setChannel(0x76);
radio.openWritingPipe(0xF0F0F0F0E1LL);
radio.enableDynamicPayloads();
radio.powerUp();
}
void loop() {
const char text[] = "Hello World";
radio.write(&text, sizeof(text));
Serial.println("sent.. ");
delay(1000);
}
The code used in the python script on the raspberry pi 4 is receive only:
import RPi.GPIO as GPIO
from lib_nrf24 import NRF24
import time
import spidev
GPIO.setmode(GPIO.BCM)
pipes = [[0xE8,0xE8,0xF0,0xF0,0xE1], [0xF0,0xF0,0xF0,0xF0,0xE1]]
radio = NRF24(GPIO, spidev.SpiDev())
radio.begin(0,17)
radio.setPayloadSize(32)
radio.setChannel(0x76)
radio.setDataRate(NRF24.BR_1MBPS)
radio.setPALevel(NRF24.PA_MIN)
radio.setAutoAck(True)
radio.enableDynamicPayloads()
radio.enableAckPayload()
radio.openReadingPipe(1,pipes[1])
radio.printDetails()
radio.startListening()
while True:
while not radio.available(0):
time.sleep(1/100)
receivedMessage = []
radio.read(receivedMessage, radio.getDynamicPayloadSize())
print("Received: {}".format(receivedMessage))
print("Translating our received message into unicode characters...")
string = ""
for n in receivedMessage:
if (n >= 32 and n <= 126):
string += chr(n)
print("Our received message decodes to: {}".format(string))
Both programs compile.
The details outputted by the RPi terminal (because of radio.printDetails()) are:
/home/pi/nrf24/lib_nrf24.py:377: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
self.GPIO.setup(self.ce_pin, self.GPIO.OUT)
STATUS = 0x03 RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=1 TX_FULL=1
RX_ADDR_P0-1 = 0xfdf9f9f9f9 0xfefefefef8
RX_ADDR_P2-5 = 0xf0 0xf1 0xf1 0xf1
TX_ADDR = 0xfdf9f9f9f9
RX_PW_P0-6 = 0x00 0x08 0x00 0x00 0x00 0x00
EN_AA = 0x0f
EN_RXADDR = 0x00
RF_CH = 0x1d
RF_SETUP = 0x00
CONFIG = 0x03
DYNPD/FEATURE = 0x03 0x01
Data Rate = 1MBPS
Model = nRF24L01
CRC Length = Disabled
PA Power = PA_MIN
I'm fairly confident that theres communcation happening between the RPi and the radio as when I disconnect the radio and re-run the python script the hex values shown above all go to 0.
I have noticed that on the youtube tutorial the RX_P_NO is different, as is the TX_FULL value.
Additionally, the RX and TX addresses are not the same is the ones entered in the python script.
I have had the radios communicating using two Arduino Uno's before. I think my inexperience with python is hindering me here.
Any help is appreciated.
Edit: In the tutorial, the python script outputs a string every second. My script outputs blank strings several hundred times a second. Perhaps there is an error with the python code as it is supposed to wait in the while loop until data is available. If not it may be an issue with the radio.available() function.
The warning you are getting is likely related to your problems.
The printDetails() output indicates a communication issue between the RPi and the radio. For example, RF_CH shows as 0x1d when it should be 0x76. This indicates a wiring or configuration issue.
My best suggestion would be to use the TMRh20 RF24 Python wrapper for the RPi. This way you are using an actively supported library, the code base is exactly the same from Arduino to RPi, and it includes known working examples.
See http://tmrh20.github.io/RF24/Python.html
Note: You need to build the C++ library first, as it is a Python wrapper for the C++ library
I am trying to create a system a part of which requires a microphone to be connected to an arduino. I haven't worked with microphones a lot.
I have connected a microphone (Adafruit Electret Microphone Amplifier - MAX9814 with Auto Gain Control ) to an arduino nano. I want to record audio data from this.
void setup() {
Serial.begin(9600);
pinMode(A2, INPUT);
}
void loop() {
if(Serial.available())
{
Serial.println(analogRead(A2));
}
}
I send the data to the computer and record it using a python script and converted it into a WAV file to make sure that the microphone is working properly. I tried multiple things, using the ADC value, scaling the ADC value between -1 and 1, converting into voltage and then scaling it, but nothing seems to work. When I play it back all I can hear is static with a few clicks where the voice should be.
Below is the python code i wrote for the configuration where I am sending the ADC value using println. Here I collect the data using pyserial library and convert it into a float. Then I normalize it between -1 and 1. Then I save it in a wav file.
import serial
import matplotlib.pyplot as plt
import sounddevice as sd
import numpy as np
from scipy.io.wavfile import write
import pyaudio
import wave
def audnorm(aud):
normaud= -1+2*((aud-np.amin(aud))/(np.amax(aud)-np.amin(aud)))
return normaud
ser = serial.Serial('/dev/ttyACM0',115200)
ser.flushInput()
sound=[]
sound2=[]
while True:
try:
ser_bytes = ser.readline()
ser_bytes2= float(ser_bytes)
sound.append(ser_bytes2)
sound2.append(ser_bytes)
print(ser_bytes+"\t"+str(ser_bytes2))
print(type(ser_bytes))
except:
print("Keyboard Interrupt")
break
print(str(len(sound)))
soundnp= np.asarray(sound)
soundnp= soundnp - np.mean(soundnp)
soundnorm= audnorm(soundnp)
soundnormstr= [str(x) for x in soundnorm]
plt.plot(soundnp)
plt.show()
plt.plot(soundnorm)
plt.show()
wf = wave.open("output.wav", 'wb')
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(10000)
wf.writeframes(b''.join(soundnormstr))
wf.close()
I have attached 2 images of the data I recorded using this code.
What am I doing wrong?
Raw Data
Normalized Data
To be recorded without distortion, the signal you're trying to record - I assume it's an audio signal - requires three things: 1) sampling at a uniform rate, 2) sampling at more than 8,000 samples per second to be able to barely understand a voice, and 3) transmitting or storing the data as fast as you acquire it.
re: 1 & 2) There is an instructable that goes into all the messy details of recording high-fidelity audio on the Arduino. It contains far more information than I could write here. See https://www.instructables.com/id/Arduino-Audio-Input/
If your application requires the Arduino to simply detect that there is a sound - such as a clapping pair of hands - you can get by with a lower and non-uniform sample rate. Search for "Arduino Clapper" to get some ideas.
I agree with Bradford. You will need to make a uniform sampling to acquire the audio signal and 8000 Hz is a minimum.
I think that you need to set a higher serial baud rate to achieve this sampling frequency. I have slightly modified your code to measure with an oscilloscope the "actual maximum frequency" of the serial "transmission" (plus the analogWrite).
void setup() {
// Serial.begin(9600);
Serial.begin(115200);
pinMode(A2, INPUT);
}
void loop() {
//if(Serial.available())
{
int val = analogRead(A2);
Serial.write(0);
}
}
On the oscilloscope, it is roughly 9 kHz frequency, sending simply zeros on the serial wire. see the attached figure. It might be doable (for speech, not for music).
I have an arduino that reads in two ints over a serial connection when I send the data from the arduino serial monitor it works as it should, but no matter what I do I can't get it to work when I send the same data from python using pySerial, I have been at this hours and have gotten nowhere
I have tried encoding the data as utf8, different encodings flushing the output buffer and have read too many other similar stackoverflow Q&As to count
I am using python 3.7.1 in Windows 10 but the code will untimately be running on a Rpi
import os
import time
import serial
ser = serial.Serial('COM7', baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=5)
print("writting")
time.sleep(0.5)
ser.write(b'4,5')
ser.write(b'\r\n')
time.sleep(0.5)
ser.flushOutput()
ser.close()
#include <SoftwareSerial.h>
byte buttonPin = 9;
const int pin_led = LED_BUILTIN; // Pin for indication LED
int sensorPin = A0;
int sensorValue = 0;
int remotePower = 0;
SoftwareSerial mySerial(11, 12); // RX, TX
void setup()
{
pinMode(pin_led, OUTPUT); // Set LED pin as output
Serial.begin(9600);
mySerial.begin(9600);
pinMode(buttonPin, INPUT_PULLUP);
}
int oldremotePower = 0;
void loop()
{
// if there's any serial available, read it:
while (Serial.available() > 0) {
Serial.println("theres Data");
// look for the next valid integer in the incoming serial stream:
int mode = Serial.parseInt();
// do it again:
int action = Serial.parseInt();
// do it again:
//int blue = Serial.parseInt();
// look for the newline. That's the end of your sentence:
if (Serial.read() == '\n') {
// constrain the values to 0 - 255 and invert
// if you're using a common-cathode LED, just use "constrain(color, 0, 255);"
mode = constrain(mode, 1, 4);
action = constrain(action, 0, 100);
mySerial.print(mode);
mySerial.print(",");
mySerial.println(action);
}
}
oldremotePower = remotePower;
sensorValue = analogRead(sensorPin);
remotePower = map(sensorValue, 0, 1023, 1, 100);
if (oldremotePower != remotePower){
//Serial.println(oldremotePower);
//Serial.println(remotePower);
}
if (digitalRead(buttonPin) == LOW) {
mySerial.println(remotePower);
}
}
I send "1,100" from the arduino serial monitor and the uno responds with "theres Data" and on the software serial it prints the values it was just sent
this works but when I try to send "1,100\r" from my python script nothing happens the script runs without error the Rx led on the uno flashes but there is no output on the software serial port It must be something wrong with my python serial code.
You are missing the part where you read from the port.
Contrary to the terminal or serial monitor, where everything that arrives to the port is immediately and automatically displayed, with pyserial you need to explicitly read bytes from the RX buffer:
incoming = ser.read() #Read one byte
incoming = ser.read(n) #Read n bytes, whit n and INT
incoming = ser.readline() #Read everything until a \n is received
incoming = ser.read(ser.inWaiting()) #Read everything in the buffer
You need to choose one of those and add it to your code.
To make sure you read everything you can add a loop to read until nothing else is waiting in the buffer and maybe a certain amount of time elapses:
timeout=time.time()+1.0
while ser.inWaiting() or time.time()-timeout<0.0:
if ser.inWaiting()>0:
data+=ser.read(ser.inWaiting())
timeout=time.time()+1.0
print(data)
This will keep reading for 1 second after the buffer is detected to be empty. I took it from here.
EDIT: As you say in the comments, you were indeed missing the read commands but that was on purpose.
Your other potential problem is the way you handle Serial.parseInt() on your Arduino code.
Serial.parseInt() reads integer values up to the delimiter (in your case the colon) but you need to explicitly call Serial.read() to swallow the delimiter itself. So just try calling Serial.read() after every Serial.parseInt() and your code should work.
One other thing you can do is to compare the result of Serial.parseInt() with 0 to check if you got a timeout.
So I have managed to make it work. (for now, I think) I put back a 2 sec wait (which I had when I first wrote this code) after opening the port in my python code and changed my write command to ser.write(bytes(b'4,5\n'))
I also removed the ser.flushOutput() and it seems to be working okay. I didn't need to make any changes to the arduino code. I have no real idea why all of a sudden it now works as the code I now have is almost identical to what I started with before I started debugging it and trying to make it work, which is infuriating to me as I have no clue what I did to fix it :<
Thanks All
I am trying to send x and y coordinates from my Python on my Raspberry Pi to a Arduino Nano. Currently, I am using serial communication, packing the coordinates with struct.pack(), but my Arduino is not receiving the coordinates the way I would expect.
import serial
import struct
ser = serial.Serial('/dev/ttyUSB0', 115200, timeout = 1)
def sendpacket(x,y) # x and y are integers
packet = struct.pack('BsBs',x, ',' , y, ',')
print packet
print ord(packet)
ser.write(packet)
I have inserted commas so that the Arduino can tell the difference between x's and y's. I know that the Arduino can only read one byte at a time, which is why I was packing the data before sending it, but I don't really understand what is going on.
I know struct.pack() converts my packet to Unicode, or at least it appears to from my above print statements. Is that what is actually being send over serial? How should I read this in the Arduino code?
Alternatively, is there a better way to send/receive xy coordinates over serial?
I am a beginner, I know/understand very little of what I am trying to do.