picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Setting up gpio using classes

Mon Oct 22, 2018 4:33 pm

When setting up a system there may be many sensors & other I/o for switches, leds etc.
Each sensor may be in its own file, using its own class & sub functions (read volts, read rpm, set pressure, set rpm, etc)
The sensor classes are imported into the main file.
Some lines (pins) may be shared among several sensors, such as serial lines
Other mode lines (pins) may be needed by more than one sensor class (such as pin to select English or metric mode, or a pin to show its valid to take a reading for several of the devices)
Should each class simply set up its own I/o as though the others do not exist (even though some I/O's are used in multiple classes).
It seems like there should be one class to setup all the I/O's & somehow the other sensor classes use that, but I'm not sure how to do that?
Maybe that is a completely wrong concept??
What is the correct method to allow the many sensors in the different classes to use the I/O's, some of which need to be looked at by multiple devices?

User avatar
B.Goode
Posts: 8021
Joined: Mon Sep 01, 2014 4:03 pm
Location: UK

Re: Setting up gpio using classes

Mon Oct 22, 2018 5:10 pm

It isn't necessarily the 'correct' (ie. mandatory or only) way, but it would be worth looking at how the gpiozero python library module is implemented.

Documentation here: https://gpiozero.readthedocs.io/en/stable/

Source code for all the python scripts here: https://github.com/RPi-Distro/python-gp ... r/gpiozero

(That's in addition to gpiozero being installed by default with the Raspbian Operating System, so these scripts are already sitting on your RPi ready to be explored.)

picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Re: Setting up gpio using classes

Mon Oct 22, 2018 6:31 pm

I'm taking a look at the gpiozero, but there is way way too much code to even know how it is all tying together.
Say I have class A and class B
They both need to look at GPIO18 (name it mysignal)

Should each one define mysignal (set up pin name, direction pullups, etc) in it's init? Then it is being done twice for the pin & not sure what the ramifications are, since there is only one physical pin. I DO know python complains and say the pin is already in use or defined...blah blah...but proceeds anyway.

Or
Have Class A & B & another class C that defines & sets up the pin(s) in one place.
If doing it this way, how do class A & B access the pin(s) defined in class C? I suppose that is my real question.

scotty101
Posts: 3648
Joined: Fri Jun 08, 2012 6:03 pm

Re: Setting up gpio using classes

Tue Oct 23, 2018 9:52 am

With gpiozero, when you configure a new pin you create an instance of one of gpiozero's classes.

If I had two devices that needed to use the same GPIO pins, I'd just pass the class a reference to a pin that has already been setup.

For example (untested example code only)

Code: Select all

from gpiozero import OutputDevice

myPin = OutputDevice(3)
myPin2 = OutputDevice(4)

device1 = MyDeviceClass(myPin)
device2 = MySecondDeviceClass(myPin, myPin2)
No custom class required to setup the GPIO pins.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Re: Setting up gpio using classes

Tue Oct 23, 2018 4:58 pm

Do you means something like this--I want both classes to be able to look at gpio3

Code: Select all

Class motorcontrol(object):
    def __init__(self,OutputDevice):
        myPin = OutputDevice(3)
        myPin2 = OutputDevice(4)
        self.device1 = MyDeviceClass(myPin)
        self.device2 = MySecondDeviceClass(myPin, myPin2)

def motor_check(self):
    if self.device1==1:  #looks at gpio3
        blah blah

# =============================
Class PressureRead(object):
    def __init__(self,OutputDevice):
        myPin = OutputDevice(3)
        myPin2 = OutputDevice(4)
        self.device1 = MyDeviceClass(myPin)
        self.device2 = MySecondDeviceClass(myPin, myPin2)

    def pressure_update(self):
        if self.device2==1:  #looks at gpio3
        blah blah

scotty101
Posts: 3648
Joined: Fri Jun 08, 2012 6:03 pm

Re: Setting up gpio using classes

Tue Oct 23, 2018 10:26 pm

No!

You've created new instances of the GPIO pins inside both classes.
DO NOT PUT THE GPIO PIN DEFINITION INSIDE ANY CLASS!
Just pass each GPIO PIN as a parameter when you create an instance of the motor control or pressure classes.
The pressure and motor class will just be aware that they will be allocated a number of GPIO pins that they can control. The specific GPIO pin numbers should not be inside the class.

If you'd just provide some information about what sensors/actuators you want to connect, it would be much easier to create an example for you.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 3:31 am

Not sure what the chips have to do with it, the topic is the same regardless of what part is used.
Have an adc CS5511, an BU2505 DAC & MPL115A1 pressure sensor, to name a few.
So want some classes:
The serial lines are shared & some gpios are shared in some of the classes. Where to define all of them to avoid double definition & how to use them in the classes?

Class DAC_BU2502
def init
def configure
def writeit
def calibration

Class sense_MPL115
def init
def configure
def readPressure
def rpm_cvt

Class ADC_CS5511
def init
def configure
def readADC
def rpm_cvt
def trigger

Another common gpio pin (output from rpi) goes to both the cs5511 & mpl115 board's for triggering of some associated circuits

PhatFil
Posts: 1302
Joined: Thu Apr 13, 2017 3:55 pm
Location: Oxford UK

Re: Setting up gpio using classes

Wed Oct 24, 2018 3:54 am

perhaps it would be worth looking into inheritance and defining a master gpio class/object with all gpio pins and a subclass for spi, another for i2c and another for 1wire etc.. https://www.python-course.eu/python3_inheritance.php

picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 4:36 am

Is that what is usually done for setting up the I/0 for all of the classes that use the I/O's?? Are there some examples or tutorials for this question? Once you declare GPIO11 as an output called doggy, you shouldn't need to (or want to) declare it again. Most examples I see barely even mention classes, or use only one class so the I/O question doesn't even come up.

Heater
Posts: 12948
Joined: Tue Jul 17, 2012 3:02 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 7:39 am

Personally I don't like to see pins and serial ports etc being accessed williy-nilly all over the source of a large program. No matter if you are using classes and objects or not.

A canonical example is using a serial port for logging. This is what software engineers like to call a "cross cutting concern", potentially every module in your program may want to generate log output. I don't think that implies they should all access the same serial port. Rather this should be abstracted away. Have a single function (or class) that talks to the serial port, then have everything else use that function/class to send log messages. This has some advantages:

1) Now it's clear in your code what is going on. You are logging, not just doing some other random thing with a serial port.

2) The serial port handling only happens in one place. It's easier to change in the future, say when you want to change you logging to go to a file or over the network etc.

3) If you ever get into using threads or an event driven programming model having lots of parts of your code trying to access the same serial port will result in a garbled mess in your logs. If log messages are all handled by a single module this in can tale care of that.

Similar considerations apply to GOIO pins SPI or I2C devices etc, etc.

In fact it applies to all shared resources like that. Which is why ultimately we have an operating system to manage access to our hardware.

picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 8:19 am

I think that is what I'm hoping to do. Seems ridiculous for each class to redefine all of the I/o's over & over. However, of course, each class must make use of the I/o's needed for what ever device(s) it is controlling. So do you have an example of how to set up? I haven't seen anything yet.

scotty101
Posts: 3648
Joined: Fri Jun 08, 2012 6:03 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 8:25 am

picandies wrote:
Wed Oct 24, 2018 3:31 am
Not sure what the chips have to do with it, the topic is the same regardless of what part is used.
Have an adc CS5511, an BU2505 DAC & MPL115A1 pressure sensor, to name a few.
Its very important and definitely different in your case. You have 2 SPI devices and an I2C device which means that you don't setup the GPIO pins in order to communicate with them. You leave that to the OS, you just access the devices made available to you by the OS. The OS's driver (actually its even lower level than the OS) manages the fact that the two different SPI devices share the same physical pin.

You use spidev for the SPI devices and smbus for I2C

Below example for the SPI devices (same approach would apply for I2C but you'd pass an I2C address rather than bus, port info)

Code: Select all

import spidev

Class DAC_BU2502:
    def __init__(self, bus, device):
        self.spi = spidev.SpiDev()
        self.spi.open(bus, device)
        self.spi.max_speed_hz = 976000
    #other class methods to configure/read
 
Class sense_MPL115:
    def __init__(self, bus, device):
        self.spi = spidev.SpiDev()
        self.spi.open(bus, device)
        self.spi.max_speed_hz = 976000
    #other class methods to configure/read
        
dac = DAC_BU2502(0,0)    #Open the DAC on SPI bus 0 port 0
mpl = sense_MPL115(0,1)     #Open the MPL device on SPI bus 0 port 1
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 2:31 pm

We haven't gotten anywhere. You still haven't answered the question...first the spi lines are bit-banged in each class. Also, the other pin (trigger_signal) goes to both boards of electronics to act as a trigger signal for that board's electronics. If the same pin is needed in multiple classes, how is it setup/handled?

scotty101
Posts: 3648
Joined: Fri Jun 08, 2012 6:03 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 3:56 pm

picandies wrote:
Wed Oct 24, 2018 2:31 pm
We haven't gotten anywhere. You still haven't answered the question...first the spi lines are bit-banged in each class. Also, the other pin (trigger_signal) goes to both boards of electronics to act as a trigger signal for that board's electronics. If the same pin is needed in multiple classes, how is it setup/handled?
You haven't gotten anywhere because you think you need to bit bang the SPI and I2C devices. I have no idea why you are doing this and this is the first time you have mentioned bit banging.
You asked if that what you were proposing was the incorrect concept, you were told it was and that you should use the OS provided drivers for SPI and I2C but still seem to be stuck on doing it the slow way.

Consider these examples (not tested and incomplete examples only)

Code: Select all

from gpiozero import OutputDevice, InputDevice

#Pins are initialised once here
cs0_pin = OutputDevice(x)
cs1_pin = OutputDevice(x)
clk_pin = OutputDevice(x)
mosi_pin = OutputDevice(x)
miso_pin = InputDevice(x)

class DAC_BU2502:
    def __init__(self,cs,clk,mosi,miso):
        #We tell the DAC class which pin it should use for chip select
        self.cs = cs
        self.clk = clk
        self.mosi = mosi
        self.miso = miso

class sense_MPL115:
    def __init__(self,cs,clk,mosi,miso):
        self.cs = cs
        self.clk = clk
        self.mosi = mosi
        self.miso = miso

dac = DAC_BU2502(cs0_pin,clk_pin,mosi_pin,miso_pin)
mpl = sense_MPL115(cs1_pin,clk_pin,mosi_pin,miso_pin)
OR

Code: Select all

class SPI_bit_bang:
    def __init__(self,cs,clk,mosi,miso):
        #store the pins here

class DAC_BU2502(SPI_bit_bang):
    #This class doesn't need an init method because it inherits from its parent.
    def write_data(self,data):
        #use the GPIO pins here

dac = DAC_BU2502(cs0_pin,clk_pin,mosi_pin,miso_pin)
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

Heater
Posts: 12948
Joined: Tue Jul 17, 2012 3:02 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 4:31 pm

picandies,
We haven't gotten anywhere. You still haven't answered the question..
Sure we have: viewtopic.php?f=63&t=225302#p1383780

The answer is "don't do that". Seems you don't like the answer.
...first the spi lines are bit-banged in each class.
That makes no difference. It's a resource that should be managed in one place, by one piece of code. Be it a class, functions in a module, or whatever. The rest of your program accesses the resource though that interface. Clean and nice.

I agree, with the comments above. If the OS device drivers can do what you want then use that.
If the same pin is needed in multiple classes, how is it setup/handled?
Don't do that. See above.
Last edited by Heater on Wed Oct 24, 2018 8:55 pm, edited 1 time in total.

scotty101
Posts: 3648
Joined: Fri Jun 08, 2012 6:03 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 4:33 pm

Heater, was your last response for me or for picandies (OP)?
I think I'm on your side with this one...
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 8:23 pm

I'm not sure why this is focusing on spi,i2c forget them for now. I have a trigger pin that must be known to two of my sensor classes.

How do you define/set that up so that both classes can tell the line is high? Not sure why this is such a tough question to get an answer.
Where does it get set up? And how do both classes get the state (without redoing the pin set up (name,direction, pullups, etc)in each class))? Stick to one gpio pin for this example.

It's a resource that should be managed in one place, by one piece of code. Be it a class, functions in a module, or whatever. The rest of your program accesses the resource though that interface (how???). Clean and nice.
This has been my only question from moment one...HOW is this setup & done?

Heater
Posts: 12948
Joined: Tue Jul 17, 2012 3:02 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 9:17 pm

@scotty101,

Sorry, I some how cut and pasted the wrong name there. Now fixed.

@picandies,
I'm not sure why this is focusing on spi,i2c forget them for now.
It is not. See my post above and others here.
How do you define/set that up so that both classes can tell the line is high? Not sure why this is such a tough question to get an answer.
It is not. See my post above and others here.

So here is one possible plan:

1) At start up your program initializes the GPIO pin. Along with what ever other initialization your program has.

2) Then it defines a function that is used to read the pin. That input pin probably represents something meaningful in your project like "heater on" or "water detected" or whatever. So it's best to name your funtion something meaningful for example "isHeaterOn", is "isWaterAlarm"

3) Generally these kind of programs then have a loop that runs around forever. That loop will no doubt call all kind of other class methods and functions. So now you can just make calls to "isHeaterOn" wherever they need to know that.

So here is another possible plan:

1) At start up your program initializes the GPIO pin. Along with what ever other initialization your program has.

2) In your loop, at the start of the loop, read the pin and place the result into a global variable.

3) Then is the rest of the code in your loop simply use that variable.

I am no Python expert so I don't like to give example Python code which may well be erroneous and misleading. But I'm sure you can find plenty of examples in Python of reading a GPIO pin and defining functions etc. There are many all over the internet.

For example: http://raspberry.io/projects/view/readi ... om-python/

picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Re: Setting up gpio using classes

Wed Oct 24, 2018 11:48 pm

I agree there should be an initial setup and initialization ...setting in/outs, pin name, pullup etc. That should happen only once & never again.

Thereafter when a class needs to look at the at pin state to possibly take some action, how can it have access to the already defined pin (without redoing the definition on its own)? Looking at pin states is one of the main things a control app will do. You mention setting up the I/o in a function & calling that by all members...would that function be available to all classes in the app? I don't think we want to use globals, since they are frowned upon.

scotty had something

Code: Select all

...class DAC_BU2502(SPI_bit_bang):
Is this including an I/o parameter in the class parenthesis something to do the trick?

like

Code: Select all

class my_io_setup():
   .blah blah 
  set up ALL the io stuff

class readpressure(my_io_set_up):
  def readPressure:    ..use the io stuff from my_io_setup
  def check_4_trigger
 def calibratepressure: 


class motor_ctrl(my_io_setup):
   def set_rpms
def check_4_trigger     ...similar to one above
  de calibrate rpms
I just want someone to verify or post that this is the correct way, or better yet to show an example

scotty101
Posts: 3648
Joined: Fri Jun 08, 2012 6:03 pm

Re: Setting up gpio using classes

Thu Oct 25, 2018 8:54 am

I've already given you several examples which show the way to do things. I will comment no further on this topic since you have clearly ignored what I have posted.

Perhaps you need to take a python tutorial so that you understand how classes work and topics such as class inheritance.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Re: Setting up gpio using classes

Thu Oct 25, 2018 10:58 pm

Hi Scotty:
Perhaps you need to take a python tutorial so that you understand how classes work
Why are you sounding so acidic? That why I posted the question--for some help on setting up I/o using several classes.

You seemed very focused about the particular chips & upset that I was bit-banging an spi. Bitbanging-seemed to be needed, since our boards are not not using the normal spi pins & I believe import RPi.GPIO as GPIO allows only certain spi pins. Speed is rather irrelevant. In any case, there are other gpios such as the switches signals that have nothing to do with spi or serial.
I went back & looked, none of your codes show how one gpio pin can be defined, then accessed by several classes that need to monitor the pin (or its equivalent state). Which code does that? If you can point that out as an example, it will be very helpful. Call the pin to be monitored in the classes mypin , say GPIO 22.

scotty101
Posts: 3648
Joined: Fri Jun 08, 2012 6:03 pm

Re: Setting up gpio using classes

Fri Oct 26, 2018 8:22 am

I said I wouldn't but here is a copy and paste from above. You haven't explained why you are deviating from the standard way of reading from SPI/I2C devices. Why are the devices not using the normal SPI pins? What design decision lead you to this scenario? The pi has a dedicated SPI device capable of very high data rates. Bit banging the pins won't get close.

Code: Select all

from gpiozero import OutputDevice, InputDevice

#Pins are initialised once here, x can be what ever pin you want
#Note that the pins are only initialised once and aren't reinitialised in each class.
cs0_pin = OutputDevice(x)
cs1_pin = OutputDevice(x)
clk_pin = OutputDevice(x)
mosi_pin = OutputDevice(x)
miso_pin = InputDevice(x)

class DAC_BU2502:
    def __init__(self,cs,clk,mosi,miso):
        #We tell the DAC class which pin it should use for chip select
        self.cs = cs
        self.clk = clk
        self.mosi = mosi
        self.miso = miso
    def config(self):
    #Example - Both classes can set the same GPIO pins.
        self.cs.on()
        self.clk.on()

class sense_MPL115:
    def __init__(self,cs,clk,mosi,miso):
        self.cs = cs
        self.clk = clk
        self.mosi = mosi
        self.miso = miso
    def config(self):
    #Example
        self.cs.on()
        self.clk.on()

#See below here. CLK, MISO, MOSI pins are shared by the instances of the two classes
#Both classes are passed a reference to a GPIO pin that has already been defined.
dac = DAC_BU2502(cs0_pin,clk_pin,mosi_pin,miso_pin)
mpl = sense_MPL115(cs1_pin,clk_pin,mosi_pin,miso_pin)
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Re: Setting up gpio using classes

Sat Oct 27, 2018 5:23 pm

Why are the devices not using the normal SPI pins? What design decision lead you to this scenario?
Not sure, that's just how the boards are....anyhow, the bit banging works & speed is plenty fast. May hack into the traces on the hats, but don't really want to tear things up.

So, how do I find the other GPIO pin state (call it mysig) in both of my classes? Each one needs the information from that pin.

Heater
Posts: 12948
Joined: Tue Jul 17, 2012 3:02 pm

Re: Setting up gpio using classes

Sat Oct 27, 2018 6:42 pm

picandies,

I'm not sure where the break down in communications is happening here.

I will ignore the details of using SPI drivers vs bit-banging. The problem you seem to have is how to share a single resource around various parts of your program.

As such I thought I provided reasonable outline plans here: viewtopic.php?f=63&t=225302#p1384072

I do wonder why you need to be messing with classes and object oriented programming. Do you really need many instances of the same class in your program? If not I would skip the classes and inheritance and all that junk.

Don't forget that if you have defined a function to read/write whatever it is on the GPIO you can pass that function as a parameter to other functions for them to use. It need not be global.

Sorry I can't provide an example in Python. As I said I'm no Python user so such an example may well be wrong and confusing. I am sure however that what I describe can be done.

picandies
Posts: 186
Joined: Wed Nov 26, 2014 5:13 pm

Re: Setting up gpio using classes

Sat Oct 27, 2018 9:09 pm

Thanks Heater, for the reply.

The problem you seem to have is how to share a single resource around various parts of your program. Yes, I think it is exactly that. not sure how its done.

I do wonder why you need to be messing with classes and object oriented programming. Do you really need many instances of the same class in your program? Maybe not--I am sorta following some examples where each chip (in my case, board) is defined in a class (file) that gets imported...very handy, since each class then has all of the specific chip/board methods & goodness of using classes. I've had good luck with very basic classes, other than this issue.

It works "ok" now, except that I'm setting up & defining the same pin in each class & this also give warnings that the pin is already in use/defined--probably from one of the other classes that set up the same pin. So double define/config/setup isn't really kosher for the pin itself. So my thought was to do all of the pin defining/setup elsewhere (maybe in a setup function or maybe its own class) & somehow connect to the classes that need it.

It would certainly seem strange that if 6 months from now we create another class that needs to know the state of some important already used pin, that it is impossible. On the other hand, no one has been able to show a python example. Maybe something like the spi lib is able to do it, but I'm not able to weave my way through 5 miles of big library code to figure out how they are doing it....I need a 15 line example for a pin. I suppose if everyone agrees it is impossible, than I'll have to throw in the towel & wonder about the benefit of using classes.

Return to “General discussion”