GPIO interrupt triggered by different pin - python-3.x

tl;dr:
Listening to a RISING event on GPIO PIN14 (with 10K pulldown resistor); Ghost RISING events when sending/receiving data on different GPIO pin;
I have the following issue:
In my technical room I have a Raspberry Pi 1B, and Raspberry Pi 3; I tested this on both units and I get the same results;
My mains meter has a flashing LED, 1000/kWh; I want to measure this using a photo resistor; The photo resistor is connected to GPIO PIN14; This setup works just fine, as long as I don't use any of the other GPIO pins.
Using the same unit I want to send some data over 433Mhz (GPIO PIN7, but as soon as I transmit data, I get RISING events on PIN14...
Across the internet I found different solutions, none of which seem to be working:
Use a different Raspberry Pi (B1 is a tad bit old)
Use a 10K pull down resistor on PIN14
Use a different power supply
Use separate power supplies for the raspberry pi, photo resistor, and 433Mhz transmitter
Using the code below, I can see expected behavior of the photo resistor and PIN14; But as soon as I startup the transmissions, the events of sending a message and RISING events on PIN14 synchronize. When I stop sending messages the listener on PIN14 stops working.
Does anyone have any idea how to fix this?
PIN14 Listener code:
import datetime
import time
try:
import RPi.GPIO as GPIO
except RuntimeError:
print(
'Error importing RPi.GPIO! This is probably because you need superuser privileges.')
delta = datetime.timedelta(microseconds=100000)
global last_electric_ping
last_electric_ping = datetime.datetime.now()
GPIO.setmode(GPIO.BCM)
GPIO.setup(14, GPIO.IN)
def electric_ping(channel):
if GPIO.input(14):
global last_electric_ping
now = datetime.datetime.now()
if delta + last_electric_ping <= now:
print(delta + last_electric_ping, end=" ")
print('ELECTRIC')
last_electric_ping = now
GPIO.add_event_detect(14, GPIO.RISING, callback=electric_ping)
while True:
continue
GPIO.cleanup()
Transmission code:
import time
from pi_switch import RCSwitchSender
sender = RCSwitchSender()
sender.enableTransmit(15) # use WiringPi pin 0
num = 1
while True:
time.sleep(1)
print("Woei!")
sender.sendDecimal(num, 24)
num += 1

Roll the drums:
Apparently I ran into a numbering issue; The BCM pin numbering says physical pin 8 is GPIO14, which is nice;
Now three guesses which number wiringPi gives to physical pin number 8... yes, number 15! Which is the one I'm trying send data to in the second script;
Now excuse while I go slap myself with a brick in the corner over there...

Related

Raspberry Pi 4: Keep the Physical Pin output remain HIGH until set to LOW

Looks like I just discovered something from the Raspberry Pi board. That is, command GPIO.output(led_pin,GPIO.HIGH) sets the output pin high only momentary. I originally thought it keeps the led_pin HIGH until I set it OFF. I was wrong. Again, I have to give time command to tell how long to keep it HIGH.
My question is, how to make the Pin output remain HIGH once set unless I set it again to LOW.
My code for keeping the Pin output HIGH for 5 seconds:
import RPi.GPIO as GPIO
import time
# To disable warning in the console
GPIO.setwarnings(False)
led_pin = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin,GPIO.OUT)
# Set the led Pin to HIGH
GPIO.output(led_pin,GPIO.HIGH)
# Keep led ON for 5 seconds
time.sleep(5)

Bluetooth advertising and scan

Hello I'm hoping someone can help me with Bluetooth advertising & scanning. This is for a school stem project.
I'm working with a circuit playground Bluefruit development board and using circuit python. Trying to implement a social distancing badge - lights up when another user is too near. General idea is to set up an advertising beacon and then switch to scan.
I've had a go at code but would appreciate someone to review it. I'm not sure if the eddystoneuid works; when I'm scanning will it only scan for my specific uid for example.
Thank you
import time
from adafruit_circuitplayground.bluefruit import cpb
import adafruit_ble
from adafruit_ble_eddystone import uid
emitter = adafruit_ble.BLERadio()
advertisement = uid.EddystoneUID(emitter.address_bytes)
receiver = adafruit_ble.BLERadio()
while cpb.switch:
# only if the switch is to the leftt the code will work
# so there's an option to turn the board off if needed.
emitter.start_advertising(advertisement)
time.sleep(0.5)
emitter.stop_advertising()
# advertises its "address" almost every half second
for advertisement in receiver.start_scan():
# then the same board scans for advertisements after
rssi = advertisement.rssi
if advertisement.rssi > -80:
# if the rssi is stronger than -80 (around 2m, yet to be certain)
cpb.pixels.fill((250, 0, 0))
time.sleep(0.2)
cpb.pixels.fill((250, 0, 0))
time.sleep(0.2)
cpb.pixels.fill((250, 0, 0))
cpb.pixels.fill((0, 0, 0))
# then the neopixels flash bright red three times, then turn off
receiver.stop_scan()
It appears that at the moment your code will trigger if detects any Bluetooth advertisement with an RSSI greater than -80 dBm. Is that what you want? Typically you would identify that the other device is broadcasting/advertising your notification service.
Typically a service like this would not use just the RSSI number. The advertisement data also includes the dBm that the advertisement was broadcast at. Using the difference between those two dBm numbers allows for a rough approximation of distance as explained in the following article: https://medium.com/personaldata-io/inferring-distance-from-bluetooth-signal-strength-a-deep-dive-fe7badc2bb6d
If all of your devices are the same and broadcasting at the same dBm then calculating the distance is less important.
So in conclusion, instead of broadcasting emitter.address_bytes, I would put some specific number that all badges would broadcast. Then when you scan look in the advertisement.ServiceData for that number. Only if it is your exposure notification, calculate if it is too close.
For further reference, here is a link to the Google/Apple Exposure Notification Bluetooth® Specification that was released last year.

Received message differs from sent message over serial connection

I am trying to connect two raspberries over a serial connection with pyserial. I wrote two little scripts, for transmitting and receiving. While there is a communication happening between those two, the received message is completely different, than the sent message.
For example if I do
serial1.write(b'hello')
on raspi1, then raspi2 receives:
print(serial2.readline().hex())
fa9b9fff
which is the hex representation of ú›Ÿÿ.
EDIT: Here is the receive and send methods:
sender:
def send_msg(_ser, _msg):
if _ser.isOpen(): # isOpen() is deprecated since version 3.0
try:
_ser.flushInput() # flush input buffer, discarding all its contents
_ser.flushOutput() # flush output buffer, aborting current output 
# and discard all that is in buffer
_ser.write(_msg)
_ser.flush()
except IOError:
print('error communicating...')
else:
print('cannot open serial port')
return
receiver:
def read_line(_ser, _eol_character=b'\n', _timeout=1, _encoding='utf-8'):
buffer = ""
timer = time.time()
while (time.time()-timer)<_timeout:
one_byte = _ser.read(1)
print(one_byte.hex())
if one_byte == _eol_character:
return buffer.encode(_encoding)
else:
buffer += str(one_byte, _encoding, errors='replace')
raise TimeoutError("Timed out while read_line(), make sure there is an EOF!")
The kind of gibberish you're getting indicates three possible causes:
-A mismatch of settings, most likely different baud rates
-Noise on the bus: frequently originating from lacking a common ground reference. This happens when you have not connected only connect the TX and RX signals but leave the GND floating (on desktop computers you'll likely have a common ground even if you don't connect the GND signals because of the safety ground on your house's wiring but on laptops or other battery-powered devices this is a problem and you have to use a third cable to connect GND on both sides of the bus).
-You're trying to communicate using different logic levels. This happens if one side of the bus is working on TTL levels (5V) and the other on 3.3V or when you have a real RS232 level (differential) combined with any of the others. Not to mention if you try to mix RS485 with RS232 or TTL, which, of course, won't work either.

i want to communicate with 'TestEquity1000' temperature chamber by using 'pyserial'

i want to set and get temperature of serial device (testequity1000) by using pyserial but not able to communicate.
cable used RS232
python 3.7
import serial
port = 'COM20'
` serial_comunication = serial.Serial(port, baudrate=9600, timeout=1)
answer = serial_comunication.read(400)
print(answer)
NEW_TEMPERATURE=45
set_temp=serial_comunication.write(b'NEW_TEMPERATURE')
print(set_temp)
abc=serial_comunication.close()
print(abc)
results:
b''
15
None
can't understand these result
Your device seems to be able to communicate on the RS232 bus but you have to use Modbus instead of the raw serial.
Quoting from the manual:
The F4 Temperature Controller has an RS-232C interface. A DB-9
connector is located on the rear panel. It is wired to accommodate a
null-modem cable. To communicate with the controller from a PC, you
need to run software that uses the Modbus RTU protocol. Each
controller function has a “register” number which can be read or
written to (when applicable). These registers are listed Chapter Seven
of the “Series F4 User’s Manual”. RS-232C Modbus programming resources
and LabVIEW drivers can be downloaded from
http://chamber.testequity.com/rs232.html
Common Modbus Registers
-Actual chamber temperature reading is register 100 (Input 1 Value).
-Actual chamber humidity reading is register 104 (Input 2 Value).
-Static temperature set point is register 300 (Set Point 1).
-Static humidity set point is register 319 (Set Point 2). •
-Temperature set point during a profile is register 4122 (Set Point 1, Current Profile Status).
-Humidity set point during a profile is register 4123 (Set Point 2, Current Profile Status).
-Decimal points are implied. For example, 1005 is actually 100.5 and -230 is -23.0.
Based on these details you can use pymodbus instead. A good starting point is this example.
You can install the package with: pip install pymodbus
So, if you want to read the Actual Chamber Temperature you need to write something similar to this:
#!/usr/bin/env python
# Pymodbus Synchronous Client Examples
# --------------------------------------------------------------------------- #
# import the various server implementations
# --------------------------------------------------------------------------- #
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
# --------------------------------------------------------------------------- #
# configure the client logging
# --------------------------------------------------------------------------- #
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s '
'%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
UNIT = 0x1
# ------------------------------------------------------------------------#
# choose the client you want
# ------------------------------------------------------------------------#
client = ModbusClient(method='rtu', port='COM20', timeout=1, baudrate=19200)
client.connect()
# ----------------------------------------------------------------------- #
# example requests
# ----------------------------------------------------------------------- #
rr = client.read_holding_registers(100, 1, unit=UNIT) #Actual chamber temperature reading
print(rr.registers[0])
# ----------------------------------------------------------------------- #
# close the client
# ----------------------------------------------------------------------- #
client.close()
You might need to change the default baudrate (according to the manual 19200) and/or the Modbus UNIT ID (UNIT 1 is the default value).
Hello I actually just finished using a little something in python. TestEquity chamber for the RS-232 you need to use modbus RTU protocol.
I'm using minimalmodbus. The other thing is that you need to make sure that you are using a null modem Tx and Rx need to be swapped in the DB9 connector.
Check the baudrate and slave address in setup, communications.
My code is here:
import minimalmodbus
TE1007C = minimalmodbus.Instrument("COM5", 1)
# Set baudrate
TE1007C.serial.baudrate = 9600
temp = TE1007C.read_register(100, 1, signed=True)
print(temp)
To set a temperature use write_register(). There are other registers that can be use.

Relay control with Raspberry Pi and Python3

below is a section of code I am using to control a relay to open electric gates via a relay which is controlled via pin 7 on a raspberry pi GPIO. The gates only need a momentary voltage (via the relay contacts) to open.
My question is, what do I need to add to this code to make the relay only switch on for 0.5 Seconds when pin 7 goes high. This would enable relay to return to the off state and then wait for the next time GPIO pin 7 goes high, the gates do not need any commands from the GPIO to close after a certain time, they close under the control of the separate gate control system.
if name=="gate":
GPIO.setmode(GPIO.BOARD) ## Use board pin numbering
GPIO.setup(int(7), GPIO.OUT) ## Setup GPIO Pin to OUTPUT
GPIO.output(int(7), state) ## State is true/false
Many thanks
Peter
In this example I will use gpiozero library instead of RPi.GPIO because I like the way, how this library handle events.
from gpiozero import Button, OutputDevice
from time import sleep
from signal import pause
buttonPin = 4
relayPin = 7
button = Button(buttonPin)
button.when_pressed = ButtonPressedCallback
relay = OutputDevice(relayPin)
def ButtonPressedCallback():
relay.on()
sleep(0.5)
relay.off()
pause()
I hope, I understood your question good.

Resources