Ik heb een probleem met de GPIO uitlezen. Onder Python 2.7 blijft hij een LOW uitlezen. Draait onder Ubuntu Armbian..


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import OPi.GPIO as GPIO
from time import sleep          # this lets us have a time delay
X=(23)
GPIO.setboard(GPIO.ZERO)        # Orange Pi Zero board
GPIO.setmode(GPIO.BOARD)        # set up BOARD GPIO numbering
GPIO.setup(X, GPIO.IN, pull_up_down=GPIO.PUD_OFF)
#GPIO.setup(X, GPIO.IN)    # set pin X as input (button)

try:
    while True:                 # this will carry on until you hit CTRL+C
        if GPIO.input(X):      # if pin X == 1
            print ("Port",X," is 1/HIGH/True")
        else:
            print ("Port",X," is 0/LOW/False")

        sleep(0.5)              # wait 0.1 seconds

finally:                        # this block will run no matter how the try block exits
    print("Finally")

Onder Python 3 werkt het wel, maar dan moet ik setboard weghalen. Is er een betere Pythondriver hiervoor. De driver van de raspberry doet het i.i.g. niet.

Ik zou nu geen nieuwe Python2 code meer willen schrijven(*).

Als dan de "setboard' onder python 3 niet werkt, moet je uitzoeken waarom dat is. Eventueel fixen of gewoon zonder doen.

Dus m.i. moet de vraag iets zijn van: "Wat is er mis met setboard onder python3?". En een antwoord begint dan met: wat werkt er niet aan setboard? Krijg je en foutmelding? Welke?

(*) Nu kan je nog apt install python2.7 doen, maar over X jaar niet meer en hopelijk is er dan nog WEL python 3, dus dat je dan nog niet je programme hoeft te herschrijven.

[Bericht gewijzigd door rew op (50%)]

Python3 zal het zijn dan. Daar ziet hij wel de waarde. Alleen het rissing en falling gebeuren uit die doc werkt niet. Dus als de sensor geactiveerd wordt dan blijft hij tellen. Maar ik heb geen goed idee hoe ik het regel dat het signaal eerst weer laag geweest moet zijn voor hij er weer 1 bij mag tellen.
Dit is het tot nu toe:


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import OPi.GPIO as GPIO
from time import sleep          # this lets us have a time delay
GPIO.setmode(GPIO.BOARD)        # set up BOARD GPIO numbering
GPIO.setwarnings(False)         # No more 'pin in use' errors
GPIO.setup(5, GPIO.IN)          # set pin X as input (button)

W=0
try:
    while True:                 # this will carry on until you hit CTRL+C
        if GPIO.input(5):       # if pin X == 1
            pass                # No use for
        else:
            W=W+1
            print (W, "Liter")

        sleep(0.1)              # wait 0.1 seconds

finally:                        # this block will run no matter how the try block exits
    print("Finally")

Gegarandeerd dat die lib gewoon het sysfs gpio filesystem gebruikt.

Dus ik zou eerst proberen of dat (gpio sysfs) wel werkt zoals het hoort, even in een shell proberen.
In /sys/class/gpio .... etc de pin exporteren en dat de waarde teruglezen etc.
Is genoeg over te vinden hoe dat moet.

Over P2.7 vs P3.x, tsja typisch python. Die grossieren in incompatible interfaces, daarom heb ik er ook een hekel aan.

[Bericht gewijzigd door henri62 op (17%)]

Nog even schematische voorstelling hoe de LJ18A3-8-Z/BX - 5V is aangesloten.

Detectie

Geen detectie

Ik heb wel iets gevonden dat ik min of meer 'werkend' heb gekregen.
https://raspi.tv/2014/rpi-gpio-update-and-detecting-both-rising-and-fa…
Er dit van gefabriekt met m'n beperkte programmeurskils.


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import OPi.GPIO as GPIO
from time import sleep          # this lets us have a time delay
GPIO.setmode(GPIO.BOARD)        # set up BOARD GPIO numbering
GPIO.setwarnings(False)         # No more 'pin in use' errors
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)          # set pin X as input (button)
# Define a threaded callback function to run in another thread when events are detected  


def my_callback(channel):
    if GPIO.input(5):     # if port 5 == 1  
        print ("Up")  
    else:                  # if port 5 != 1  
        print ("Down") 

  
# when a changing edge is detected on port 5, regardless of whatever   
# else is happening in the program, the function my_callback will be run  

GPIO.add_event_detect(5, GPIO.BOTH, callback=my_callback)



try:
    while True:                 # this will carry on until you hit CTRL+C
        if GPIO.input(5):       # if pin X == 1
            pass


        sleep(0.1)              # wait 0.1 seconds
except KeyboardInterrupt:  
    GPIO.cleanup()       # clean up GPIO on CTRL+C exit  
GPIO.cleanup()           # clean up GPIO on normal exit  

resultaat:

Er zit wat 'rommel' op het Up signal

Daar het kennelijk alleen op het Up signaal zit, lijkt het mij dat ik er een soort softwarematige flipflop met een set en reset in moet brouwen.

Alleen krijg ik de 'data' niet uit dat def routine gepeuterd. Anders zou ik ook nog alleen de downs als hele liter tellen overwegen. Alhoewel een heel rondje van het 1 liter wijzertje mij beter lijkt.

Toch nog iets gevonden deze ochtend :P
Het lijkt kennelijk heel eenvoudig.
De code uit deze tutorial gevist.


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import OPi.GPIO as GPIO
from time import sleep          # this lets us have a time delay
GPIO.setmode(GPIO.BOARD)        # set up BOARD Pin GPIO numbering
GPIO.setwarnings(False)         # No more 'pin in use' errors
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Pin 5 set up as an input, pulled down on detection

W=0

try:
    while True:                             # this will carry on until you hit CTRL+C
        GPIO.wait_for_edge(5, GPIO.FALLING) # Wait for pin 5 go to low
        W=W+1                               # If Pin 5 is going low count one liter 
        print (W,"Liter")                   # Show me how well this works.
except KeyboardInterrupt:  
    GPIO.cleanup()       # clean up GPIO on CTRL+C exit  
GPIO.cleanup()           # clean up GPIO on normal exit  

Het resultaat lijkt stabiel, geen valse Upjes. :)

De nieuwe sensor op de nieuwe watermeter in de bestaande 'digitale' gefrommeld. Cron @ reboot opdracht aangepast naar in Python3 starten. Gereboot. 1 Liter in een maatbeker getapt, lijkt te kloppen. Ik zal de stand van de mechanische meter opschrijven en dan over een tijd eens kijken hoeveel de afwijking bedraagt. Dit is i.i.g. de uiteindelijke code geworden.


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import time
import OPi.GPIO as GPIO
from time import sleep          # this lets us have a time delay
GPIO.setmode(GPIO.BOARD)        # set up BOARD Pin GPIO numbering
GPIO.setwarnings(False)         # No more 'pin in use' errors
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Pin 5 set up as an input, pulled down on detection


f = open("/water/Liter", "r")	# Read Liters on startup
wa=float(f.read())
f.close()

def datum():					# Format datum
	return format(time.strftime('%d-%m-%Y'))

def tijd():						# Format time
	return format(time.strftime('%H:%M:%S'))

wam=0							# Set and declare daily counter

while True:						# Run forever
	f = open("/water/Liter", "r")		# Read from liter
	wah=float(f.read())					# Declare and put liter in wah
	f.close()							# Close reading file
	GPIO.wait_for_edge(5, GPIO.FALLING) # Wait for pin 5 go to low
	wa=wa+1								# If Pin 5 is going low add one liter to counter
	wam=wam+1							# If Pin 5 is going low add one liter to daily counter

	if wa != wah:						# If wa not equal to wah then
		f = open("/water/Liter", 'w')	# open Liter file
		f.write(str(wa))				# write new wa value to Liter file
		f.close()						# close Liter file
		m3=round(float(wa)/1000, 3)		# Calculate wa liters to metric volume
		f = open("/water/M3", 'w')		# open metric file
		f.write(str(m3))				# write new metric value to metric file
		f.close()						# close metric file
		f = open("/water/Dagteller: "+str(datum()), 'w')	# Write daily file and consumption in
		f.write(str(wam))									# liters to daily file
		f.close												# Close writing file
	if tijd() == "00:00:00":								# If there is a new day then
		wam=0												# reset daily counter to zero
pass

De watermetersensor werkt al een speer tot nu toe. Nog nul afwijking tussen de mechanische meter en het digitale meet proces. En dan ben ik al weer 300 liter verder. :P

Het is zinvol om namen van variabelen zo goed mogelijk te beschrijven. Vb :
wa -> waterteller_stand_liter
wam -> waterteller_stand_m3
wah ->waterverbruik_uur
Idealerwijze heb je dan ook geen commentaar meer nodig. Denk eraan, code wordt 100 maal meer gelezen (hoe had ik dat weeral gedaan) dan geschreven !
Flankdetectie kan ook zeer eenvoudig met een hulp variabele worden gedaan :

if((water_sensor==high)&(old_watersensor==low)) {watercount++);
old_watersensor=watersensor;

Hier zal er geteld worden bij een opgaande flank. Omdat het in de loop gebeurt, moet het signaal wel langer actief zijn dan de tijd die de loop nodig heeft voor één doorgang !
Voor zeer korte signalen, kan je beter voor interrupts kiezen.

Ter info: Ik heb de python "wacht op flank" gebruikt om te wachten totdat ik op een knop druk. Als ik op die knop heb gedrukt dan moet er een scan gemaakt worden. (kan ook via het fontpaneel van de scanner, maar dan kost het 32 toetsaanslagen).

Het wachten op de flank in de loop is dus letterlijk wachten. Daar kwam ik achter toen de dagteller niet gereset werd. Dat betekent dat er heel veel uitgesloopt kon worden. Uiteindelijk heb ik alleen het aantal liters nodig om te uploaden naar PVoutput, de extended data. Daar gaat ook het gasverbruik naar toe en wat er actueel in huis verbruikt wordt.

@ RP6conrad:
Ik meen daar C-code te herkennen. Maar ik wil sowieso de opgaande flank niet gebruiken omdat die regelmatig valse spikes geeft. Zelfs nog als ik de IO pin rechtstreeks aan de nul leg middels een draadbrug. De neergaande flank vertoont die fratsen niet.

Ik heb i.i.g. geprobeerd de commentaren in het Python3 script zo duidelijk mogelijk te maken. Ik zag net ook dat de code tags of het tekstvenster van CO wat moeite had met de tabs. Kennelijk is in mijn editor Geany een tab 4 posities en op CO 10 o.i.d. Dus ik moest de ctrl-c-v effe handmatig corrigeren. :P

@ rew: :)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Watermeter with LJ18A3-8-Z/BX - 5V detector on Elster/Honeywell e.d. V200 watermeter.

import OPi.GPIO as GPIO			# IO pins acces for Python 
GPIO.setmode(GPIO.BOARD)		# set up BOARD Pin GPIO numbering
GPIO.setwarnings(False)			# No more 'pin in use' errors
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)	# Pin 5 set up as an input, pulled down on detection
f = open("/water/Liter", "r")			# Read from Liter on startup
wa=float(f.read())				# Declare wa in liters and set counter to last value
f.close()					# Close file reading

while True:					# Run forever
	GPIO.wait_for_edge(5, GPIO.FALLING)	# Wait for pin 5 go to low
	wa=wa+1					# If Pin 5 is going low add one liter to counter
	f = open("/water/Liter", 'w')		# open Liter file
	f.write(str(wa))			# write new wa value to Liter file
	f.close()				# close Liter file
	m3=round(float(wa)/1000, 3)		# Calculate wa liters to metric volume
	f = open("/water/M3", 'w')		# open metric file
	f.write(str(m3))			# write new metric value to metric file
	f.close()				# close metric file
pass