I am working on an project and I have a rfid reader mrfc522 connected to my arduino uno.. I am using pyfirmata to communicate between Arduino and python. so I am trying to fetch the data of the card scanned by RFID reader to display in the python console.. any suggestions on how it can be accomplished?
i tried everything possible but nothing worked .. i tried sysex ,i tried subsitiutions to values for the program but nothing works`
/*
Example sketch/program showing how to read data from a PICC to serial.
This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
Example sketch/program showing how to read data from a PICC (that is: a RFID Tag or Card) using a MFRC522 based RFID
Reader on the Arduino SPI interface.
When the Arduino and the MFRC522 module are connected (see the pin layout below), load this sketch into Arduino IDE
then verify/compile and upload it. To see the output: use Tools, Serial Monitor of the IDE (hit Ctrl+Shft+M). When
you present a PICC (that is: a RFID Tag or Card) at reading distance of the MFRC522 Reader/PCD, the serial output
will show the ID/UID, type and any data blocks it can read. Note: you may see "Timeout in communication" messages
when removing the PICC from reading distance too early.
If your reader supports it, this sketch/program will read all the PICCs presented (that is: multiple tag reading).
So if you stack two or more PICCs on top of each other and present them to the reader, it will first output all
details of the first and then the next PICC. Note that this may take some time as all data blocks are dumped, so
keep the PICCs at reading distance until complete.
#license Released into the public domain.
Typical pin layout used:
MFRC522 Arduino Arduino Arduino Arduino Arduino
Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Pro Micro
Signal Pin Pin Pin Pin Pin Pin
RST/Reset RST 9 5 D9 RESET/ICSP-5 RST
SPI SS SDA(SS) 10 53 D10 10 10
SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16
SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14
SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15
*/
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522
delay(4); // Optional delay. Some board do need more time after init to be ready, see Readme
// Show details of PCD - MFRC522 Card Reader details
void loop() {
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
// Dump debug info about the card; PICC_HaltA() is automatically called
mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}`
Related
I'm currently trying to rotate a motor on my Arduino Uno through serial communication from my Raspberry Pi 3. My code itself currently works however sometimes when running the python script the motor will not turn or indicate any response. From what I've been able to find online, I feel like I'm sending signals faster than the Arduino is reading them, and I can't seem to find a way to minimize the delay and make my motor response consistent.
Here is my Arduino code:
#include <Stepper.h>
#define STEPS 128
Stepper stepper(STEPS, 8, 10, 9, 11);
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.read() == 50) {
stepper.setSpeed(8); // rpm
stepper.step(128); // do n steps -- corresponds to one revolution in one minute
}
else if (Serial.read() == 51) {
stepper.setSpeed(8); // rpm
stepper.step(-128); // do n steps -- corresponds to one revolution in one minute
}
}
Here is my Python code
import serial
import time
ser = serial.Serial('/dev/ttyACM0', 9600)
time.sleep(1)
num="3"
ser.write(bytes(num.encode()))
Also I'm not sure how Arduino is reading my ser.write, as when num = 2, I see "50" in my Serial Monitor, when num = 3, "51" appears in my Serial Monitor, and so forth.
Thank you!
Serial communication is always done in Bytes. So whatever you send through your interface will be received as a sequence of Bytes. As you encoded your "3" as UTF-8 it will be sent as 0x33 (51). Your "2" is 0x32 (50) respectively.
Increasing the baudrate as suggested in a comment won't help you as it will only increase the speed data is transmitted/received. Without a measurement you won't notice a difference betweeen sending a single byte with 9600 or 115200 baud.
As long as both device operate on the same baudrate and you do not exceed the max baudrate of any device (somewhere around 2 million baud for Arduino Uno) you cannot send to fast. (given a suitable cable and distance)
You might run into problems with too long cables but that's several meters for 9600 baud even in noisy industrial environment.
Usually you wait for data to be available in the receive buffer befor you read.
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
Maybe not doing so causes some delay. I cannot tell for sure as you did not provide the length of the observed delay.
If the Arduino is already running when you execute your Python code I don't see any other issue with your code. If it is booting while you send you might observe some delay because of the Arduino bootloader. It will wait some time for possible firmware updates befor it starts the actual application code.
Small pieces of data may sit around in the output buffer before being sent. Try using Serial.flush() after write to let the os know you want the data sent asap.
So far, I was exploring Python with Arduino using pySerial. I made some projects where pySerial reads something from the serial port.
import serial
arduinoSerialData = serial.Serial('com11',9600) #Create Serial port object called arduinoSerialData
while (1==1):
if (arduinoSerialData.inWaiting()>0):
myData = arduinoSerialData.readline()
print (myData)
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.
}
For now, my code looks something like this. How can I make use of my ultrasonic sensor in Python and send signals to my Arduino program? In other words, can I make my Arduino file read from the Python file that I have or it is only one direction?
pySerial allows for communication over serial in both directions. On the Arduino side, you need to call Serial.read where appropriate to read data stream from Python. In Python, you just need to send data using the function serial.write. If using Python 3, input to serial.write needs to be in byte format.
I have tried connecting Arduino to the raspberry Pi through USB cable. The Arduino board is connected to an Ultrasonic sensor and sends a serial message of either 0 or 1 based on whether it finds a barrier in a certain distance (very simple code). The problem is this : I'm trying to get the Raspberry Pi to read the Arduino code AND play a mp3 file at the same time but for some reason that doesn't seem to work ! I'm not sure if the problem lies in coding or If maybe it's impossible for Pi to respond to a message sent from Arduino to the serial monitor(It would be really sad if that's the case). Any help would be very appreciated
This is the Arduino Code (I'm using UNO board) :
/*
HC-SR04 Ping distance sensor:
VCC to Arduino
Vin GND to Arduino GND
Echo to Arduino pin 12
Trig to Arduino pin 11 */
#include <NewPing.h> //downloaded from the internet & unzipped in libraries folder in Arduino Directory
#define TRIGGER_PIN 11 // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN 12 // Arduino pin tied to echo pin on the ultrasonic sensor.
int maximumRange = 70; // Maximum range needed
int minimumRange = 35; // Minimum range needed
long duration, distance; // Duration used to calculate distance
void setup() {
Serial.begin (9600);
pinMode(TRIGGER_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
}
void loop() {
/* The following trigPin/echoPin cycle is used to determine the distance of the nearest object through reflecting soundwaves off of it */
digitalWrite(TRIGGER_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIGGER_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER_PIN, LOW);
duration = pulseIn(ECHO_PIN, HIGH);
distance = (duration/2) / 29.1; //formula to convert the value measured by the ultrasonic sensor into centimeters
if (distance >= maximumRange || distance <= minimumRange)
{
Serial.println("0"); //means the path is clear
}
else {
Serial.println("1"); //means there is an obstacle in front of the ultrasonic sensor !
}
delay(50); //Delay 50ms before next reading.
}
And this is the python code that I used in my Pi (I have Raspberry Pi 2):
NOTE : I have commented the parts that don't work since I tried many different code combinations shown below
import serial
import RPi.GPIO as GPIO
import sys
import os
from subprocess import Popen
from subprocess import call
import time
import multiprocessing
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
arduinoSerialData = serial.Serial('/dev/ttyACM0', 9600)
while True:
time.sleep(0.01)
if(arduinoSerialData.inWaiting()>0):
myData = arduinoSerialData.readline()
print(myData)
if myData == '1': #THIS IS WHERE THE PROBLEMS START
#os.system('omxplayer sound.mp3') #tried this didn't work
#os.system('python player.py') #which is basically a python program with the previous line in it, also not working!
# I even tried enclosing that part (after if myData == '1') in a while loop and also didn't work !
Firstly, your IF condition doesn't look right. I don't see how distance <= minimumRange means the path is clear.
Next, you are writing a line to the serial port; a line that could be either 0\r\n or 1\r\n. Then you're reading a line from the Arduino, returning one of the two aforementioned possibilities. You're then comparing the line you've read, to 1. Neither 0\r\n nor 1\r\n is equal to 1, so its no surprise that the condition is never true. You can fix this in a number of ways:
Change the Serial.println() to Serial.print()
Change arduinoSerialData.readline() to arduinoSerialData.readline().rstrip()
Change the condition to if 1 in myData:
Another thing to remember is, read() returns a bytes object in Python 3 not a string as in Python 2. So any comparison involving literals should make sure to include the requisite b'' envelope. Like, if you strip the CRLF from the read data, your condition should instead be if myData == b'1':.
I am stuck and dont know why. I am trying to transmit from an Arduino Nano to a RPi via the TX and Rx pins respectively.
This my code so far:
Arduino TX:
void setup(){
Serial.begin(9600);
}
void loop(){
bProgramLoop = 1
while(bProgramLoop == 1){
Serial.write(1);
}
}
The Raspberry Side:
import serial
oSer = serial.Serial("/dev/ttyAMA0",baudrate=9600,timeout=1)
while True:
sSerialInput = oSer.read(1)
#sSerialInput = oSer.readline()
print sSerialInput
After loading the sketch onto the Arduino and starting the python script, the Raspberry simply does not read anything.
NOTE:
I have connected the Tx pin from the Arduino to the Rx pin from the RPi via a Voltage divider and some jumper wires.
I have tried "readline()" too, but no luck
Any suggestions?
I have found the a solution to the problem I am having. I am still a proper noob, but as far as I can figure it out, sending serial data over the Tx pin is problematic because it is used by the usb port and then to your PC.
Thus the solution is to use the SoftwareSerial library. I have modified my two code sketches as follows:
Arduino:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(4,3); // (RX,TX) - Pin Setup for any digital pins you want as Rx or Tx
void setup(){
Serial.begin(9600);
mySerial.begin(57600); // initialize serial communication with serial pin
}
void loop(){
bProgramLoop = 1
while(bProgramLoop == 1){
mySerial.write("Anything");
}
}
Raspberry:
import serial
oSer = serial.Serial("/dev/ttyAMA0",baudrate=9600,timeout=1)
while True:
sSerialInput = oSer.readline()
print sSerialInput
As it is I am able to transmit data from the Arduino to the RPi. HOWEVER, I am still having issues converting the string to an integer or float.
see this post for details: Python readline() returns string that wont convert to int or float
I'm trying to use a Beaglebone Black running Angstrom (3.8 kernel) to communicate with devices on a half-duplex RS-485 network at 9600-N-8-1.
I'm trying to use an RS-485 Breakout board similar to this one: https://www.sparkfun.com/products/10124, except the chip is a MAX3485 http://www.maximintegrated.com/datasheet/index.mvp/id/1079. I bought the board pre-assembled with pins and a terminal strip. A friend of mine tested it with an oscilloscope and declared that the RS-485 board does work. The board has five pins that connect to the BBB. 3-5V (Power), RX-I, TX-O, RTS, and GND.
I've disabled HDMI support on the BBB so that the UART4_RTSn and UART4_CTSn pins will be available.
mkdir /mnt/boot
mount /dev/mmcblk0p1 /mnt/boot
nano /mnt/boot/uEnv.txt
#change contents of uEnv.txt to the following:
optargs=quiet capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN
Then I've found an overlay to enable UART-4 with RTS/CTS control:
/*
* Modified version of /lib/firmware/BB-UART4-00A0.dtbo to add RTS so we can reset Arduinos
*/
/dts-v1/;
/plugin/;
/ {
compatible = "ti,beaglebone", "ti,beaglebone-black";
part-number = "BB-UART4-RTS";
version = "00A0";
exclusive-use = "P9.13", "P9.11", "P9.15", "P8.33", "P8.35", "uart4";
fragment#0 {
target = <0xdeadbeef>;
__overlay__ {
pinmux_bb_uart4_pins {
pinctrl-single,pins = <
0x070 0x26 /* P9_11 = UART4_RXD = GPIO0_30, MODE6 */
0x074 0x06 /* P9_13 = UART4_TXD = GPIO0_31, MODE6 */
/* need to enable both RTS and CTS, if we only turn on RTS then driver gets confused */
0x0D0 0x26 /* P8_35 = UART4_CTSN = lcd_data12, MODE6 */
0x0D4 0x06 /* P8_33 = UART4_RTSN = lcd_data13, MODE6 */
/* 0x040 0x0F /* P9_15 = GPIO1_16 = GPIO48, MODE7 failed attempt to put DTR on gpio */
>;
linux,phandle = <0x1>;
phandle = <0x1>;
};
};
};
fragment#1 {
target = <0xdeadbeef>;
__overlay__ {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <0x1>;
};
};
__symbols__ {
bb_uart4_pins = "/fragment#0/__overlay__/pinmux_bb_uart4_pins";
};
__fixups__ {
am33xx_pinmux = "/fragment#0:target:0";
uart5 = "/fragment#1:target:0"; /* Not a mistake: UART4 is named uart5 */
};
__local_fixups__ {
fixup = "/fragment#1/__overlay__:pinctrl-0:0";
};
};
Compiled and Enabled the overlay:
cd /lib/firmware
dtc -O dtb -o BB-UART4-RTS-00A0.dtbo -b 0 -# BB-UART4-RTS-00A0.dts
echo BB-UART4-RTS:00A0 > /sys/devices/bone_capemgr.*/slots
Hooked up the 485 board to the BB like this
3-5V to P9_05 (VDD_5V)
RX-I to P9_13 (UART4_TXD)
TX-O to P9_11 (UART4_RXD)
RTS to P8_33 (UART4_RTSn)
GND to P9_01 (DGND)
In python I'm trying to use the serial port like this:
import serial
ser = serial.Serial('/dev/ttyO4', baudrate=9600, rtscts=True)
ser.write(list_of_byte_dat)
I know the program works because when I use a USB to RS-485 converter on /dev/ttyUSB0 and set rtscts=False the communication works in both directions just fine. But I can't get communication to work correctly using the RS-485 board.
I have two issues with the RS-485 board, both deal with RTS.
The RTS on the board works backwards from the way I expect it to. When I apply voltage on the RTS pin of the rs485 board the RTS led on the board goes off and the board will not transmit. When I remove voltage from the RTS pin the RTS led turns on and the board will transmit. How do I reverse the polarity of the UART_RTSn pin on the BBB?
Temporary solution: I've made a small bone script program that uses UART4_RTSn pin as input. It turns on a different GPIO when the UART4_RTSn pin is off and turns off that same GPIO pin when the UART4_RTSn pin is on. Then hooked up the RTS pin on the rs485 board to the GPIO pin instead of the UART4_RTSn pin.
This seems to be a poor solution, but it does make the RTS on the RS485 board come on at the correct time when echoing to the /dev/ttyO4 from the command line.
How can I change the polarity of the UART4_RTSn pin either by adjusting the hardware configuration or by changing the configuration in pyserial?
This brings me to the second issue
As I stated in problem 1 the UART4_RTSn pin will work automatically (but backwards) for me when echoing a value to the tty port like this:
echo -en '\x02\xFD\xCD......' > /dev/ttyO4
This will make the UART4_RTSn led blink while the data is being transmitted. If I have it setup without the bonescript mentioned above, then it will be on normally and blink off while transmitting. If I use my bonescript hack then it will be off normally and blink on while transmitting (which is what I want). However this only works when using echo from the command line. When I use python and setup the serial port the UART4_RTSn pin becomes inactive. It will not blink while transmitting. As soon as I make the statement in python:
ser = serial.Serial('/dev/ttyO4', baudrate=9600, rtscts=True)
The UART4_RTSn pin shuts off and stays off. It does not blink when sending information using ser.write(stuff). As a result the rs485 board is not enabled for transmission. How do I get the UART4_RTSn pin to work automatically in pyserial? I've tried setting rtscts=False and it did not work.
I am able to use ser.setRTS(True) or ser.setRTS(False) to manually toggle the pin value so I know I'm using the correct pin and that it is being recognized. But I don't want to toggle the UART4_RTSn pin directly. I want it to work automatically when the serial port is transmitting data and it does when using echo, but not in Python.
Any help would be greatly appreciated.
RTS is normally an active low signal, I suspect the reason that you see data being transmitted with echo is that it is not using RTS/CTS (leaving it high) and so is only able to transmit data.
According to a post on http://www.raspberrypi.org/phpBB3/viewtopic.php?f=26&t=29408
If you enable hardware flow control (CRTSCTS in "man termios", or
"stty crtscts -F /dev/ttyAMA0", or pySerial rtscts=True), then sending
will take place only when CTS is asserted. RTS will be asserted except
when the kernel input buffer is full. The kernel input buffer is about
one page or 4KB, so your application has to get well behind with its
reads before RTS actually changes.
So check that CTS is being asserted (pulled to ground) outside of your board. However I don't think this will give you the right control over RTS that you need.
So, for your application you should disable hardware flow control (rtscts=False) and manually control RTS with setRTS(1) before a write and setRTS(0) afterwards.
If you are still not seeing data get through to the device, try swapping the A & B wires - A/B labelling is (frustratingly) not consistent across RS485 devices. It is better to use D+/D- labelling if possible in your own applications.
Use ioctl to change the logic level...
98 struct serial_rs485 rs485conf;
99
100 /* Enable RS485 mode: */
101 rs485conf.flags |= SER_RS485_ENABLED;
102
103 /* Set logical level for RTS pin equal to 1 when sending: */
104 rs485conf.flags |= SER_RS485_RTS_ON_SEND;
105 /* or, set logical level for RTS pin equal to 0 when sending: */
106 rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
107
108 /* Set logical level for RTS pin equal to 1 after sending: */
109 rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
110 /* or, set logical level for RTS pin equal to 0 after sending: */
111 rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
112
113 /* Set rts delay before send, if needed: */
114 rs485conf.delay_rts_before_send = ...;
you can use pnp transistor/ p channel mosfet/ logic gate not - inverter like 7404
maybe you have to flush write buffer after write operation
ser.write(....)
ser.flush()