I am trying to use joan's pigpio for python to try to write a command from a rpi3 GPIO pin to a peripheral device. the peripheral device uses UART and when it receives a data packet it will then perform the corresponding function.

example |-----dataBuffer----| start devID size packetCount index futureByte | highByte LowByte | 255 1 2 1 1 0 | 3 195 | |00000011 11000011|

start: beginning of packet
devID: id of device
size: # of command bytes, only one command at a time and each command is 2 bytes so this number is always 2
packetCount: total # of packets in the transmission.(only 1 packet at a time)
index: place of this packet within set of packets
futureByte: not used, keeps the data packet even
dataBuffer: 0 to 16 byte buffer. bc only 1 command is sent at a time, the buffer will only contain 2 bytes(the high byte and the low byte)

peripheral device byte format:
start bit: yes
bit order: 0...7
parity bit: no
baud rate: 9600

I have not yet reached the point where I am actually sending commands to the peripheral. For now I just trying to write on a GPIO using pi.wave_send_once() and verify that this is working correctly using joans piscope and my bench oscope. Here is my script:

import sys
import difflib
import pigpio
import time
import os
from os import system

system('sudo pigpiod')

# GPIO pin constants
BAUD = 9600    # 9600
TX = 22        # NOT builtin gpio 14

#create instance of pigpio class
pi = pigpio.pi()
if not pi.connected:
    os.system("sudo pigpiod")
    pi = pigpio.pi()

pi.set_mode(TX, pigpio.OUTPUT) # set GPIO 14 as an output

def send_command(packet):
        pi.wave_add_serial(TX, BAUD, packet, bb_bits=8) #bb_bits=16
        wid = pi.wave_create()
        pi.wave_send_once(wid)   # transmit serial data
        while pi.wave_tx_busy(): # wait until all data sent
        print('The packet\n{}\n was sent!'.format(packet))

packet = b'3'
#packet = b'00000011'
#packet = '00000011'


Here is the output of the wave_get functions:

control blocks: 14 max cbs: 25016 microseconds: 1146 max micros: 1800000000 pulses: 7 max pulses: 12000

Here is a screenshot of piscope:

piscope screenshot

As you can see something is wrong. First of all the timing is wrong, at 9600baud each pulse should be 104usec.

  1. Does anyone have any ideas how to fix the timing problem? I have tried fixing with the core_freq=250 and dtoverlay workarounds I read about, but this did not solve the problem.
  2. will this method of sending pigpio waves still work for me once I start sending the larger complete packets(64bits)?
  3. the pigpio library has a function for filtering glitches/noise. Should i be using these? If so i did not really understand how to use them please explain or point to tutorial/example.

script ot send command `

# GPIO pin constants     
BAUD = 9600    # 9600
TX = 5       

#create instance of pigpio class
pi = pigpio.pi()
if not pi.connected:
    os.system("sudo pigpiod")
    pi = pigpio.pi()

#set mode of tx pin
pi.set_mode(TX, pigpio.OUTPUT) # set GPIO 14 as an output

# fatal exceptions off (so that closing an unopened gpio doesn't error)
pigpio.exceptions = False


# fatal exceptions on
pigpio.exceptions = True

def wave_dbg(msg):
        cbs = pi.wave_get_cbs()
        max_cbs = pi.wave_get_max_cbs()
        micros = pi.wave_get_micros()
        max_micros = pi.wave_get_max_micros()
        pulses = pi.wave_get_pulses()
        max_pulses = pi.wave_get_max_pulses()
        print('-------------[DBG - wave]------------------------------')
        print('control blocks: {}    max cbs:    {}'.format(cbs,max_cbs))
        print('microseconds:   {}    max micros: 
        print('pulses:         {}    max pulses: 

def send_command(packet):
        print('inside function:  {}'.format(type(packet)))
        print('inside function:  {}'.format(packet))
        #self.wave_dbg('before wave clear')
        #self.wave_dbg('after wave clear')
        pi.wave_add_serial(TX, BAUD, packet, bb_bits = 32) #bb_bits=16
        #self.wave_dbg('after serial add')
        wid = pi.wave_create()
        #self.wave_dbg('after wave creation')
        pi.wave_send_once(wid)   # transmit serial data
        #self.wave_dbg('after wave sent')
        while pi.wave_tx_busy(): # wait until all data sent
        print('The packet\n{}\n was sent!'.format(packet))
        wave_dbg('end of function')

commands returned from sniffer
r_eye_norm = bytearray(b'\xff\x01\x02\x01\x01\x00\x03\xc3')
r_eye_cons = bytearray(b'\xff\x01\x02\x01\x01\x00\x03\xc5')
r_eye_dila = bytearray(b'\xff\x01\x02\x01\x01\x00\x03\xc4')
br30 = bytearray(b'\xff\x01\x02\x01\x01\x00\x04d')
br_apnea = bytearray(b'\xff\x01\x02\x01\x01\x00\x04`')
br5 = bytearray(b'\xff\x01\x02\x01\x01\x00\x04a')

r_eye_norm = bytearray(b'\x01\x02\x01\x01\x00\x03\xc3')
r_eye_cons = bytearray(b'\x01\x02\x01\x01\x00\x03\xc5')
r_eye_dila = bytearray(b'\x01\x02\x01\x01\x00\x03\xc4')
br30 = bytearray(b'\x01\x02\x01\x01\x00\x04d')
br_apnea = bytearray(b'\x01\x02\x01\x01\x00\x04`')
br5 = bytearray(b'\x01\x02\x01\x01\x00\x04a')


piscope screenshot

script for sniffer uart_sniffer.py '
import datetime as dt import time import pigpio

TX = 6 # pin 29

TX_data = []
    pi = pigpio.pi() # connect to local host
    #pi.set_mode(RX, pigpio.INPUT)
    pi.set_mode(TX, pigpio.INPUT)

    pigpio.exceptions = False
    pigpio.exceptions = True

    #pi.bb_serial_read_open(RX, 9600, 8)
    pi.bb_serial_read_open(TX, 9600, 8)

    print('-----------------DATA SOFTWARE SERIAL------------------------')
    while True:
        (countTX, dataTX) = pi.bb_serial_read(TX)
        if countTX:

except KeyboardInterrupt:
    with open('uart_read.txt', 'w') as f:
        for item in TX_data:
            f.write('%s\n' % item)


This may be a misunderstanding of how traditional serial data is transmitted. If there is no level transition the line is not toggled. So if you send 0x00 there will be 8 bit times between a level change.

I changed packet to [0xaa, 0xaa, 0xaa] and got the following screen shot.


You can see that the bit time is 104µs.

Glitch filtering only applies to data being received by a GPIO.

  • I understand that i will not see the line toggle if there is no level change. what i realized is that if i send the packet in an array like in your example, i.e. packet = [0x03] , i see the expected output. Before when i was sending the packet, i was sending it as a string. i.e. packet = '3'. This is when i did not see what was expected. I think this might have to do with the way python stores string variables. I will have to investigate further. Thanks for your help and thanks for your awesome pigpio! Dec 4 '18 at 14:18
  • im still not completely undertstanding how this works. you sent the packet [0xaa,0xaa,0xaa]. I would think this would be 24 bits therefore 2496usec, however when i look at the screenshot and output of picsope when i run it. it looks like there are 28bits therefore 2912usec. Am i missing something? what are the extra 4 bits? Dec 6 '18 at 16:28
  • Each number has a start bit and an end bit. That is used to allow synchronisation between sender and receiver. E.g. see ece.northwestern.edu/local-apps/matlabhelp/techdoc/…
    – joan
    Dec 6 '18 at 16:53
  • ok so i have made some progress. i setup a script to sniff the that my peripheral device i receiving from its actuall commercial controller(tablet). when i use the tablet to tell the device to turn off pump. the sniffer prints a bytearray(b'\xff\x01\x02\x01\x01\x00\x04d'). however when i use my above code to send the same command ie pkt = bytearray(b'\xff\x01\x02\x01\x01\x00\x04d') the device doesnt work properly. I thought it might be bc of the start bit you mentioned above so i removed the \xff from pkt but this does not work. does the wave_send_once() auto generate the start/end bytes?@joan Dec 14 '18 at 18:33
  • is there something im missing about the pigpio wave_send_once()? Dec 14 '18 at 18:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.