I am trying to use Arduino analog pins (A0-A5) as digital pins (D14-D19) with pyfirmata. I'm doing a simple blink test with D14 (or A0) to test this:
#!/usr/bin/python
# Blink test with analog as digital pins
# Import required libraries
from pyfirmata import Arduino, util
from pyfirmata import INPUT, OUTPUT, PWM
from time import sleep
# Associate port and board with pyFirmata
port = '/dev/cu.usbmodem1451'
board = Arduino(port)
# Pause to sync
sleep(1)
led = board.get_pin('d:14:o')
time = 1
while True:
led.write(1)
print ("On")
sleep(time)
led.write(0)
print ("Off")
sleep(time)
To enable analog pins to act as digital pins, I've gone into pyfirmata's boards.py file (as show in the github repo at https://github.com/tino/pyFirmata/blob/master/pyfirmata/boards.py) and changed line #3 from
digital': tuple(x for x in range(14)),
to
digital': tuple(x for x in range(20)),
I don't get an error when I run my python script, but the LED doesn't blink (don't worry, I'm positive the LED was in the right way).
Does anyone know how I can effectively instantiate digital pin 14 as an output pin with pyfirmata (as in the line led = board.get_pin('d:14:o'))
By the way (not that I think this affects anything) but I'm running Mac OSX with Yosemite.
Thank you!
The standard firmata that we use in Arduino, makes all analog pins input by default. So instead of changing anything in boards.py file, go to standard firmata file in arduino ide and find this ...
switch (mode) {
case PIN_MODE_ANALOG:
if (IS_PIN_ANALOG(pin)) {
if (IS_PIN_DIGITAL(pin)8) {
pinMode(PIN_TO_DIGITAL(pin), INPUT);
Now comment the pinMode line so that the firmata does not make any analog pin input
Now go to void setup() function and explicitly define nature of analog pins as shown below.
Firmata.begin(57600);
while (!Serial) {
}
pinMode(14,OUTPUT);
pinMode(15,INPUT);
pinMode(16,INPUT);
pinMode(17,INPUT);
pinMode(18,INPUT);
pinMode(19,INPUT);
digitalWrite(14,LOW);
Related
I am having some problems reading analog values from my Arduino Mega using pyfirmata.
I use Arduino Mega with a Mega Sensor Shield.
I would like to read analog values from a HW-201 IR sensor (pin A5).
I have uploaded the Standard firmata sketch on Arduino IDE, and I am running the following code using Anaconda Spyder:
import serial
import serial.tools.list_ports
from pyfirmata import ArduinoMega, util
from time import sleep
def readArduinoPort():
COM = []
ports = list(serial.tools.list_ports.comports())
for p in ports:
if "Arduino" in p.description:
COM.append(str(p.device))
return COM
COM = readArduinoPort()
board = ArduinoMega(COM[0])
pin = board.get_pin('a:5:i')
it = util.Iterator(board)
it.start()
try:
while True:
print(pin.read())
sleep(0.1)
except KeyboardInterrupt:
pass
Now, this code runs just fine the first time I use it, generating numbers close to 1 when the sensor is detecting proximity and numbers close to 0 when not detecting anything.
However, whenever I try to run the Iterator a second time (without restarting the kernel), the code generates seemingly random numbers (almost like the pin was floating, like nothing was connected to it).
Any idea why this is happening? Is this a normal behavior?
Thank you!
I already checked these questions that do not entirely address my issue:
arduino pyfirmata analog reading
Analog readings on Arduino returns wrong values
I have the same result by not having anything pinned to pin A5 of the Arduino Mega.
I wasn't sure, but I tried adding:
board.analog[5].enable_reporting()
before the iterator and then:
board.analog[5].disable_reporting()
but nothing changed.
Board Differences
I ran into the same problem. I own both a Mega and an Uno and needed to select the appropriate Board and Processor in the tools menu:
Tools > Board > _board_
Tools > Processor > _processor_
The Raspberry Pi has a Broadcom BCM 2835 chip allowing it to interface with SPI devices on its GPIO pins. I encountered a problem adressing LEDs in a 8x8 Matrix via SPI.
I want to adress single LEDs on the matrix, but I haven't figured out, which bytes adresses which LED(s).
SPIdev seems to be the right library for this purpose und I stumbled upon this snippet of code:
import spidev
import time
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 7629
# Split an integer input into a two byte array to send via SPI
def write_pot(input):
msb = input >> 8
lsb = input & 0xFF
spi.xfer([msb, lsb])
# Repeatedly switch a MCP4151 digital pot off then on
while True:
write_pot(0x1FF)
time.sleep(0.5)
write_pot(0x00)
time.sleep(0.5)
Does anyone know which values adresses (a) specific LED(s)?
In C/C++ adressing works very well via the wiringpi-library, a useful documentation can be found here:
http://wiki.52pi.com/index.php/RPI-RGB-LED-Matrix_SKU:EP-0075
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 hooked up a 16X2 LCD to the pi via a MCP23017 GPIO expander. The problem that I am facing is that the LCD code below works inside normal functions or when I call it individually. But it does not work inside any of the threads in my program.
#!/usr/bin/python
# Example script to show usage of MCP230xx GPIO extender to drive character LCD.
from Adafruit_CharLCD import Adafruit_CharLCD
from Adafruit_MCP230xx import MCP230XX_GPIO
bus = 1 # Note you need to change the bus number to 0 if running on a revision 1 Raspberry Pi.
address = 0x20 # I2C address of the MCP230xx chip.
gpio_count = 8 # Number of GPIOs exposed by the MCP230xx chip, should be 8 or 16 depending on chip.
# Create MCP230xx GPIO adapter.
mcp = MCP230XX_GPIO(bus, address, gpio_count)
# Create LCD, passing in MCP GPIO adapter.
lcd = Adafruit_CharLCD(pin_rs=1, pin_e=2, pins_db=[3,4,5,6], GPIO=mcp)
lcd.clear()
lcd.message(" Adafruit 16x2\n Standard LCD")
links to library programs,
https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/blob/master/Adafruit_CharLCD/Adafruit_CharLCD.py
https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/blob/master/Adafruit_MCP230xx/Adafruit_MCP230xx.py
part of my actual program:
def switch():
mcp.config(0, mcp.INPUT)
mcp.pullup(1,1)
if ((mcp.input(1)>>1))
lcd.clear()
lcd.message("Switch open")
switchthread=threading.thread(target=switch)
switchthread.start()
Can anyone please tell me how to get the LCD commands working in the threads ?
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()