abelectronicsuk / abelectronics_python_libraries Goto Github PK
View Code? Open in Web Editor NEWPython Libraries to work with Raspberry Pi expansion boards from AB Electronics
License: GNU General Public License v2.0
Python Libraries to work with Raspberry Pi expansion boards from AB Electronics
License: GNU General Public License v2.0
Hello,
I am using the ADC Differential Pi to do some telemetry on batteries. I have a thermistor/current sensor and voltage sensor (all calculated by reading voltage drop). However, when I get a timeouterror I see that the values freeze on the last one before the timeout. Is there something I can do to avoid this?
def __read_adc(self):
self.__adc = ADCDifferentialPi(0x6a, 0x69, 18)
self.__adc.set_pga(1)
self.__fail_count = 0
while not self.stop:
try:
timestamp = datetime.now()
self.dataset[0] = ((self.__adc.read_voltage(1) + self.config.vcor) * self.config.Gv)
self.dataset[1] = (self.__adc.read_voltage(4) - self.config.icor) / self.config.vgain
if -15 <= self.dataset[1] <= 15:
self.dataset[1] = 0
tcor = self.calc_temperature(self.calc_resistance(self.__adc.read_voltage(3)))
self.dataset[2] = (self.__adc.read_voltage(8)/self.config.celcius) + tcor
except KeyboardInterrupt:
LOGGER.info("Stopping")
break
except:
LOGGER.exception("Unexpected: ")
sys.exit()
self.__fail_count += 1
time.sleep(0.2)
Unexpected:
Traceback (most recent call last):
File "/home/pi/scmeter/strom_diagnostic.py", line 82, in __read_adc
tcor = self.calc_temperature(self.calc_resistance(self.__adc.read_voltage(3)))
File "/usr/local/lib/python3.5/dist-packages/ADCDifferentialPi/ADCDifferentialPi.py", line 136, in read_voltage
raw = self.read_raw(channel)
File "/usr/local/lib/python3.5/dist-packages/ADCDifferentialPi/ADCDifferentialPi.py", line 199, in read_raw
raise TimeoutError(msg)
TimeoutError: read_raw: channel 3 conversion timed out
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 34, 50, 769936)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 34, 50, 769936)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 34, 51, 776438)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 34, 52, 782307)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 34, 53, 788786)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 34, 54, 794547)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 34, 55, 800444)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 34, 56, 806269)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 34, 57, 813006)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 34, 58, 815608)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 34, 59, 817479)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 35, 0, 821270)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
'table': 'testing',
'timestamp': datetime.datetime(2019, 3, 11, 17, 35, 1, 825087)}
{ 'data': [ { 'Current': -217.7699303136222,
'Temperature': 14.410154208169065,
'Voltage': 47.31267686170213}],
Hello.
First I would like to thank you for your wonderful products.
In the past I have found on the ADC Pi's page about the information of the resistors installed on it (in order to be able to measure voltages >2v). But I forgot to save.
Today when I used ADC Pi to measure the output signal of a pressure sensor (PSE563, with 1-5v output, https://docs.rs-online.com/3ae2/0900766b80df5651.pdf) I didn't get the right result. I discovered this sensor uses a 1000-ohm resistor as the output impedance so it falsified the measurement results.
I couldn't find the contact section on your website so I wrote this post. I hope you can tell me about the resistor information on your ADC Pi.
Thank you.
Describe the bug
It is possible to call read_raw(0) and read_raw(-1), this does not raise an exception.
To Reproduce
from ADCPi import ADCPi
adc = ADCPi(0x68, 0x6B, 18)
adc.read_raw(0)
adc.read_raw(-1)
print("If you see this printout, the two above lines failed to give an exception")
Expected behavior
read_raw(X) with X anything other than the numbers 1 to 8 should raise a ValueError: read_raw: channel out of range
There is a problem with mixed spaces and tabs in ABE_helpers.py in the ADCPi folder.
The lines around the if/elif statement have a single tab mixed in with the spaces, which is causing Python to throw an exception. Can you please fix this?
In ABElectronics_IOPi.py:
bugs:
suggestion:
I think it is an unnecessary and perhaps invalid assumption in the init method that the initial state of the pins should be low. On many devices, the default (off) state is a high pin, so this just turns everything on as soon as you instantiate the class. I suggest leaving each pin in the state it was when you acquire the handle, by replacing the following lines in the init method:
bus.write_byte_data(self.address,self.GPIOA,0x00)
bus.write_byte_data(self.address,self.GPIOB,0x00)
with the following:
self.portA_val = bus.read_byte_data(self.address,self.GPIOA)
self.portB_val = bus.read_byte_data(self.address,self.GPIOB)
thus reading the initial state and setting the instance variables to match the device, rather than the other way around.
Thanks for publishing this. It really gave me a big head-start on where I would be if I had to start from scratch.
From: Elliott
Board: Raspberry Pi Zero V1.1
OS: Raspbian Bullseye
Python Verison: 3.12.2 https://www.python.org/downloads/
RTC Board: https://www.abelectronics.co.uk/p/70/rtc-pi
RTCLib: As per https://github.com/abelectronicsuk/ABElectronics_Python_Libraries/
Installed: As per Tutorial https://www.abelectronics.co.uk/kb/article/30/rtc-pi-setup-on-raspberry-pi-os
and https://www.abelectronics.co.uk/kb/article/1/i2c-part-2-enabling-i2c-on-the-raspberry-pi
No other boards added & no other GPIO pins used
IDE: Thonny
Tutortial has worked the RTC is keeping correct date and time. Have confirmed by turning off WiFi and rebooting several times with WiFi off.
Error when running demo_rtcgetdate.py from RTCPi see attached file Errno16
The UU at 0x68 indicates that there is another device or driver at the same address.
Debugging Output see attachment
Steps Tried
Pins soldered and secure
Redid tutorial
Internet search has shown
https://www.linuxquestions.org/questions/linux-embedded-and-single-board-computer-78/what-is-error-ioerror-%5Berrno-16%5D-device-or-resource-busy-4175599788/
Implies
2 Solutions
From the dump the issues seems to be with i2c-1
Resolution sort
Thank you for your time and attention
Measured Voltages about 8% too low
I was measuring 2.46V at ADC input and it was reporting 1.31V. And I wanted the exact value! I slowed down the bus and around 200kHz, the values are correct.
Recommendation
Please slow down SPI by default as precision is very important. For speed, you may explain in a comment that it can be augmented but sub-estimate begins to be over 5% somewhere around 1MHz.
** Line of source code **
self.__spiADC.max_speed_hz = (200000)
I have a use case with a couple of different scripts logging and watching ADCPi channels. If one script calls ADCPi.read_voltage() before the first was finished, both scripts become totally unresponsive.
This situation with several simultaneous calls for ADCPi.read_voltage() can easily be triggered by starting a few instances of the demo script:
python demo-readvoltage.py &
When I start the 4th or 5th test script they all freeze without raising any exception.
It would be nice if the ADCPi.read_voltage() could handle this situation by raising an exception when it fails. Perhaps there could be a timeout if for the underlying i2c reading?
Would you mind if I converted this to an actual python library for ease-of-use purposes?
Library: ABElectronics_Python_Libraries/RTCPi
CMD as per readme
git clone https://github.com/abelectronicsuk/ABElectronics_Python_Libraries.git
Error Msg: Support for password authenication was removed on August 13, 2021
See https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloing-with-https-urls
FATAL: Authentication failed
As I said in #16 it would be nice to use the pip-version of smbus.
Another benefit of this would be that you could publish the project on PyPI and make it installable via pip. That would make it easier for others to use it in their projects, because they can specify the needed version in their setup.py.
Best Luke
Hi there
getting this error running the demo
with python 2.7 and 3
Traceback (most recent call last):
File "demo_pwm.py", line 49, in
main()
File "demo_pwm.py", line 39, in main
pwm.set_pwm_freq(1000)
File "/usr/local/lib/python2.7/dist-packages/ServoPi/ServoPi.py", line 112, in set_pwm_freq
newmode = (oldmode & 0x7F) | 0x10
TypeError: unsupported operand type(s) for &: 'exceptions.IOError' and 'int'
Any idea how to resolve this issue?
Thanks in advance
It appears that when I read channels 1 and 2, I get the same reading. Same goes with all pairs (3,4: 5,6: 7,8). Have you been able to test this with some known voltage? Say a pot or something? I'm just wondering if I'm crazy or not.
Hey guys,
is there a good reason, why you use the smbus package which needs to be installed via apt?
I tried to run your modules with smbus2 which is installable via pip and it works without problems.
The big benefit of using this would be, that you can add it as a dependancy in the setup.py.
If you would like, I could make a pull request for that.
If you prefer keeping the apt-version, I would like to make a fork of your project and publish it on PyPI with the changes if this is ok for you.
Best Luke
When initialising the instance, apart from the ADCPI timeout, there are no other useful exceptions. I'm having problems initialising and trying to narrow down the where the issue might be.
Also, the internal function that gets the I2C addresses might be useful if it could be called from the instance, again to see if the problem is Pi or ADC related.
Thanks!
In ServoPi.py @ line 255, there's the following condition check:
if channel >= 0 and channel <= 15:
Which accept the value 0, and fail for value 16.
But the set_pwm() function except a value between 1-16
It should be:
if channel >= 1 and channel <= 16:
I am running Linux raspberrypi 4.9.39-v7+ #1 SMP Wed Jul 26 05:31:05 CEST 2017 armv7l GNU/Linux
and i2cdetect gives the following output:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- 6d -- --
70: -- -- -- -- -- -- -- --
Unfortunately, the example (copied to another file) fails with:
Traceback (most recent call last):
File "test_ADC_I2C_MCP3428.py", line 60, in <module>
main()
File "test_ADC_I2C_MCP3428.py", line 39, in main
adc = ADCPi(0x68, 0x6d, 12)
File "/usr/local/lib/python3.4/dist-packages/ADCPi/ADCPi.py", line 109, in __init__
self.set_bit_rate(rate)
File "/usr/local/lib/python3.4/dist-packages/ADCPi/ADCPi.py", line 261, in set_bit_rate
self.__bus.write_byte(self.__adc1[0], self.__adc1[1])
File "/usr/local/lib/python3.4/dist-packages/smbus/util.py", line 59, in validator
return fn(*args, **kwdefaults)
File "/usr/local/lib/python3.4/dist-packages/smbus/smbus.py", line 121, in write_byte
raise IOError(ffi.errno)
OSError: 5
As you see, I adapted the address of the second ADC to 0x6d
, as for some (to me currently unknown) reason i2cdetect
would not detect it reliably on it's default address.
global name 'TimeoutError' is not defined
When the TimeoutError is raised in Python 2.7 it results in a NameError. From what I can tell TimeoutError wasn't introduced until Python 3.3
Recommendation
Please define a custom "TimeoutError" class in the beginning of the library for systems using Python 2. It would be very helpful to be able to handle this error in my code where I import the library when this happens. Right now I have to handle it as a "NameError" instead.
I'm playing with IO Pi Zero module connected to NanoPi Duo2 (Armbian Focal) , I can have it working as expected but it need little tweaking.
The Constructor of class IOPi in line 134
device = platform.uname()[1]
is getting the "name" of board but in my case the hostname is returned. And that is obviously useless :-(
My workaround was just to change line 132 to:
i2c__bus = 0
as my NanoPi Duo2 bus is 0.
What do you thing about idea of providing the "bus number" as additional parameter to the constructor. This will easily expand the coverage of your library to many boards without touching other part of library. Because now every board should be somehow "hardcoded" inside the __get_smbus() method.
for example:
def __init__(self, address, initialise=True, bus=-1)
then if bus != -1 don't check the "board type" - just use passed value as i2c_bus.
First of all, thanks for all the information and code you provide for the IOPi plus board, it makes it working with it so much easier and enjoyable.
I know the IOPI Plus board is not intended to be used this way, but I am using my Thinkpad laptop VGA i2c bus to interface with it. The python library works quite well, but I had to place a very short time.sleep(0.01) after __bus.write_byte_data() and other bus interactions because if I don't it seems like the board can't catch up and SMBus() throws me an IOError: [Errno 6] No such device or address.
Is there a more elegant way to deal with this?
Jardi.
P.S.
My reason for trying this is that I am planning on moving my Home Assistant instance from the Pi to an Intel NUC but I have a whole bunch of doors and windows sensors interfacing with it through an IOPi Plus board which I would also like to adapt to the NUC. My plan is to convert your IOPi.py library into a more generic MPC23017 library that can be use in any other linux system with an I2C bus, and since I don't have a NUC yet I am doing some testing using my Thinkpad's VGA port.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.