Using pyserial to write and read AT command data from GSM module - python

Im playing around with a Raspberry Pi, Breakout Board and GSM module. I'm having problems with the serial read data. It seems to be very speratic, with lots of blanks lines and various odd entries that look to be from the terminal (ssh login field prompt). Im simply trying to read the input response for an AT command. Reading the AT Command manual for my GSM, the responses are very specific so I am looking to read just the response im looking for. I am new to serial interfacing like this so any suggestions on best practise would also be appreciated.
#!/usr/bin/python
import time
import serial
import traceback
import netifaces as ni
import RPi.GPIO as GPIO
def resetModule(resetModulePin):
GPIO.output(resetModulePin, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(resetModulePin, GPIO.LOW)
time.sleep(0.1)
def switch(onModulePin):
GPIO.output(onModulePin, GPIO.HIGH)
time.sleep(2)
GPIO.output(onModulePin, GPIO.LOW)
def writeAT():
i = 0
while True:
ser.flushInput()
ser.flush()
out = ''
ser.write('AT\r')
time.sleep(1)
if ser.inWaiting() > 0:
out += ser.read(12)
print 'GSM Is Up'
return out
else:
i += 1
if i > 3:
print 'GSM Down'
print 'Resetting Module'
resetModule(resetModulePin)
time.sleep(5)
print 'Turning On GSM'
switch(onModulePin)
time.sleep(5)
i = 0
try:
resetModulePin = 15
onModulePin = 13
GPIO.setmode(GPIO.BOARD)
GPIO.setup(onModulePin , GPIO.OUT)
GPIO.setup(resetModulePin, GPIO.OUT)
ser = serial.Serial(port='/dev/ttyAMA0', baudrate=115200)
ser.isOpen()
answers = ['yes', 'y']
while True:
out = writeAT()
if out != '':
print out
break
question = raw_input('Do you want to powerdown GSM?:').lower()
if question in answers:
print 'Powering Off GSM'
switch(onModulePin)
ser.close()
GPIO.cleanup()
except KeyboardInterrupt, e:
GPIO.cleanup()
except Exception,e :
traceback.print_exc()
GPIO.cleanup()
OUTPUT (note the blank lines)#Debugging
pi#raspberrypi:~/Desktop $ sudo python Newpy
GSM Down
Resetting Module
Turning On GSM
GSM Is Up
Do you want to powerdown GSM?:

Try ser.write('AAAAAAAT') per this. Apparently the SIM908 on the GSM breakout board tries to automatically detect the baud rate, and you have to give it some extra data in order to do so.
Edit Or try this (post of Tue Nov 25, 2014 11:41 pm) — check the setting of the "charge" jumper on the SIM908.

Related

IndentationError: unexpected indent...FRUSTRATING

I'm very new at Python scripting and am working on a script to turn on a fan when my Raspberry Pi3 reaches a specific temp. I've been trying to debug my code all day and found I can't figure out what's wrong. Here is my code:
import os
import sys
import signal
import subprocess
import atexit
import time
from time import sleep
import RPi.GPIO as GPIO
pin = 18
maxTMP = 60
def setup():
GPIO.setmode(GPIO.BCM)
GPIO.setup(pin, GPIO.OUT)
GPIO.setwarnings(False)
return()
def setPin(mode):
GPIO.output(pin, mode)
return()
def exit_handler():
GPIO.cleanup()
def FanON():
SetPin(True)
return()
def FanOFF():
SetPin(False)
return()
try:
setup()
while True:
process = subprocess.Popen('/opt/vc/bin/vcgencmd measure_temp',stdout =
subprocess.PIPE,shell=True)
temp,err = process.communicate()
temp = str(temp).replace("temp=","")
temp = str(temp).replace("\'C\n","")
temp = float(temp)
if temp>maxTMP:
FanON()
else:
FanOFF()
sleep(5)
finally:
exit_handler()
Here is my error:
File "/home/pi/Scripts/run-fan.py", line 36
while True:
^
IndentationError: unexpected indent
I've tried to indent every way possible. I need help.
Thanks!
I want to preface this with, you should use four spaces for your indentation. If you do, it will be way, way easier to see problems like the one you have here. If you use an IDE like Spyder or PyCharm, there are settings that automatically highlight indentation problems for you (regardless of how many spaces you want to use).
That said, with your current indentation scheme of one-space-per-indent, you want to replace your bottom block with this:
try:
setup()
while True:
process = subprocess.Popen('/opt/vc/bin/vcgencmd measure_temp',stdout =
subprocess.PIPE,shell=True)
temp,err = process.communicate()
temp = str(temp).replace("temp=","")
temp = str(temp).replace("\'C\n","")
temp = float(temp)
if temp>maxTMP:
FanON()
else:
FanOFF()
sleep(5)
If you used four spaces instead of one on your original code, it would have looked like this:
try:
setup()
while True:
process = subprocess.Popen('/opt/vc/bin/vcgencmd measure_temp',stdout =
subprocess.PIPE,shell=True)
temp,err = process.communicate()
temp = str(temp).replace("temp=","")
temp = str(temp).replace("\'C\n","")
temp = float(temp)
if temp>maxTMP:
FanON()
else:
FanOFF()
sleep(5)
There's another problem here, which is that your while True block will currently never exit (maybe you want a break statement somewhere).

Python xbee library no output for incoming frames

I am using 2 XBee pro S1, I want to read the packets received by the co-ordinator on my PC , it is enabled with API_2 and all other connections are done properly, I can see the packets with XCTU, I am using the python xbee library , but it gives no output :
The Code :
import serial.tools.list_ports
from xbee import XBee
import serial
ports = list(serial.tools.list_ports.comports())
for p in ports: #print the list of ports
print p
def toHex(s):
lst = []
for ch in s:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0'+hv
hv = '0x' + hv
lst.append(hv)
def decodeReceivedFrame(data):
source_addr_long = toHex(data['source_addr_long'])
source_addr = toHex(data['source_addr'])
id = data['id']
samples = data['samples']
options = toHex(data['options'])
return [source_addr_long, source_addr, id, samples]
PORT = '/dev/ttyUSB0'
BAUD_RATE = 9600
ser = serial.Serial(PORT, BAUD_RATE)
print "Serial ports initialised...."
xbee = XBee(ser,escaped=True)
print "XBee object created"
while True:
try:
response = xbee.wait_read_frame()
sleep(0.5)
decodedData = decodeReceivedFrame(response)
print decodedData
print "data decoded"
except KeyboardInterrupt:
break
ser.close()
The port number and baudrate are connect, I change it to the appropriate portnumber every time I replug the coordinator to my PC.
My output looks like :
Serial ports initialised....
XBee object created
It stays like that and gives no output, even if I see the RX led blinking.
Below is the code written with only pyserial :
import serial
from time import sleep
port = '/dev/ttyUSB0'
baud = 9600
ser = serial.Serial(port, baud)
data = ""
while True:
try:
while ser.in_waiting:
sleep(1)
data = ser.read()
print data
except KeyboardInterrupt:
break
ser.close()
It gives the following output.
Could someone kindly help.
Are you sure you have the correct serial port and baud rate? Does the xbee package support API mode 2? It might only work with API mode 1.
Does that package have methods for accessing the raw byte stream instead of trying to read frames? Can you configure it to throw exceptions on parsing errors?
I would start with just printing response until you see that you're receiving data. And why include the sleep() call in that loop?
I'm not sure what you're trying to accomplish in toHex() but you might want to look at the Python method struct.unpack() or replace all of the work you do on hv with '0x%02X' % ord(ch).

Getting updates from Ardunio with PySerial only every 2 minutes instead of 1 minute

I have an Arduino that reports time (in seconds), voltage, current and joules ever 60 seconds. In the serial monitor like this:
time,voltage,current,joules
60,1.45,0.39,0.57
120,1.45,0.39,1.13
180,1.45,0.39,1.70
240,1.45,0.39,2.26
...
However the following python script I don't get this result:
import serial
ser = serial.Serial('COM5', 9600)
logfile = open("batterytest.log", 'w')
while True:
if ser.readline() == b'Test Complete!':
logfile.close()
exit()
logfile.write(ser.readline().decode("utf-8"))
logfile.flush()
Instead I see results every 120 seconds:
time,voltage,current,joules
120,1.13,0.02,0.05
240,1.13,0.02,0.09
360,1.13,0.02,0.14
480,1.13,0.02,0.19
....
Looks like it may miss the in-between data point due to some timing issue. You can try to use putty to see if your arduino in fact output the right data points.
For your PySerial program, I would add a variable "data" to store your serial readline first, then perform your logic on it.
import serial
ser = serial.Serial('COM5', 9600)
logfile = open("batterytest.log", 'w')
while True:
data = ser.readline()
if data == b'Test Complete!':
logfile.close()
exit()
logfile.write(data.decode("utf-8"))
logfile.flush()
Also, depending on your Arduino output timing, you may consider adding a timeout value for your serial read by:
ser = serial.Serial('COM5', 9600, timeout = 1 )
# Here the time out is 1 second

Finding string Python Arduino

I have a little script in Python which I am brand new to. I want to check if a certain word appears in ser.readline(). The syntax for the If statement is not right and I am not sure how to lay this out so it continuously reads the serial for the word "sound". I've attached an output image below so you can see how it is printing. I'd like to trigger an MP3 as it finds the word "sound" but as of yet I haven't even managed to get it to print a confirmation saying its found the word.
import serial
import time
ser = serial.Serial('COM6', 9600, timeout=0)
while 1:
try:
print (ser.readline())
time.sleep(1)
**if "sound" in ser.readline():
print("foundsound")**
except ser.SerialTimeoutException:
print('Data could not be read')
time.sleep(1)
You may be reading from the port more often than you intend to. I would call ser.readline() just once per iteration of your main loop:
while True:
try:
data = ser.readline().decode("utf-8") # Read the data
if data == '': continue # skip empty data
print(data) # Display what was read
time.sleep(1)
if "sound" in data:
print('Found "sound"!')
except ser.SerialTimeoutException:
print('Data could not be read')
time.sleep(1)
can you try:
import serial
import time
ser = serial.Serial('COM6', 9600, timeout=0)
while 1:
try:
line = ser.readline()
print line
time.sleep(1)
**if "sound" in line:
print("foundsound")**
except ser.SerialTimeoutException:
print('Data could not be read')
time.sleep(1)

How to read input from port and print to terminal

here's the situation:
I have two stamps, one connected to port: /dev/ttyUSB1, and one external one, unconnected. The external one has a (Contiki based) program on it to send (every 2 seconds) a single letter across to the stamp that is plugged into the computer. stamp plugged into the computer has a program, also Contiki based, which reads this information via a radio signal.
Now, I have written a python program, making use of pyserial, which aims to read the information coming into the port and display it in terminal. I know the message is arriving correctly as I can print the message from the stamp connected via USB to terminal fine. But I am having trouble reading the information from the python code.
import serial, time, threading
ser = serial.Serial()
ser.port = "/dev/ttyUSB1"
ser.baudrate = 9600
ser.bytesize = serial.SEVENBITS
ser.parity = serial.PARITY_EVEN
ser.timeout = 0.1
ser.rtscts = 1
try:
ser.open()
except Exception, e:
print "error open serial port: " + str(e)
exit()
if ser.isOpen():
try:
numOfLines = 0
while True:
print ser.read()
numOfLines = numOfLines + 1
time.sleep(2)
if (numOfLines >= 50):
break
ser.close()
except Exception, e1:
print "error communicating...: " + str(e1)
else:
print "cannot open serial port "
When run, instead of printing the expected letter sent from the stamp every couple of seconds, it will print a few consistent, yet random letters. For example:
w
z
z
w
g
z
g
z
z
z
w
z
w
There is no output from the program when I remove the USB connected to the stamp. So it must be reading something from the port... Any help would be much appreciated.
It sounds like it could be a problem with the baudrate. you didn't post the code that does this:
ser = serial.Serial('/dev/ttyUSB1', timeout=1, baudrate=9600, rtscts=1)

Categories