PiicoDev Requests/Suggestions

Hi Stephen,

Welcome to the forum!!
Awesome, I’m keen to see what you make :smiley:

I can attest to the Qwiic connectors working but there are a couple of gotchas with STEMMA on the electrical side, sometimes they can feed 5V through on the Vcc line, damaging the sensor.

You check out Core’s progress on The Factory episodes over on YouTube!

Liam.

5 Likes

Good to know about Stemma! Thanks!

4 Likes

Hi Core Electronics Team,

Just watched Brenton’s new Makerverse 2 Channel Motor Driver video…

And thinking robotics and the control of motorised models…

Is there a market for a PiicoDev single channel DC/Stepper motor module and a Brushless motor module?

Using I2C as a communication method, with either the addition of a high current power supply feed as a 6-wire bus, or just the 4-wire I2C with separate power supplies for each motor, could be extremely useful.

Thank You

5 Likes

how about an onboard audio out with a DAC controller chip and the output via a 3.5 mm phono socket…think this would spark the interest of quite a few users…

5 Likes

PiicoDev I2C Address Adaptor

I’m working on a project that would use two SparkFun Micro-pressure sensors - and I have just discovered that they have a fixed I2C address.

Luckily I am using a Pi-Pico/Micropython for development so can use the 2nd I2C channel on the Pico… or I could configure a PIO.

An alternative possible solution could be for a PiicoDev I2C Address Adaptor using a ATiny 806-m which would respond to an alternative address value and modify the packet address to message an attached sensor via a 3rd PiicoDev connector (on the south edge of the board?)… This would work well for the RP-4 and Micro:Bit as they don’t have a 2nd I2C channel like the Pico.

The PiicoDev I2C Address Adaptor could have it’s own address (also programmable?) to allow set up for configuration and a 2nd virtual address for the sensor.

[For larger numbers of sensors with an address conflict, then a SparkFun/Adafruit I2C mux could be used]

5 Likes

Yeah and if you want a different address you order a different part number. Strange way of doing it, leads to selling more parts I guess. Some other I2C devices allow for reprogramming of the address, much more practical. (see extract from Honeywell data sheet)

Some Python code ( has not been tested !!! ) using the PiicoDev Unified Library and along the same lines of the driver code for other PiicoDev sensors. Based on the Arduino driver code and Honeywell data sheet. Ignored the EOC and Reset pins, these need extra GPIO connections.

Maybe I am completely wrong, but this is a new area for me, so fun, will test code when I get part.
Cheers
Jim

"""
Honeywell Micro Pressure Sensor - MPR
Device in Standby Mode normally, send command, device enters Operating Mode, sensors pressure, when done flags EOC pin and Status byte.

Send 0xAA 0x00 0x00 to start reading.
Wait for status or EOC pin or at least 5ms.
Read 4 bytes, status, data 24:16, data 15:8, data 7:0

"""
from PiicoDev_Unified import *

compat_str = '\nUnified PiicoDev library out of date.  Get the latest module: https://piico.dev/unified \n'

_MPR = 0x18
MAXIMUM_PSI = 25
MINIMUM_PSI = 0

BUSY_FLAG = 0x20
INTEGRITY_FLAG = 0x04
MATH_SAT_FLAG = 0x01

OUTPUT_MAX 0xE66666
OUTPUT_MIN 0x19999A

class PiicoDev_MPR(object):     
    def __init__(self, bus=None, freq=None, sda=None, scl=None, addr=_MPR):
        try:
            if compat_ind >= 1:
                pass
            else:
                print(compat_str)
        except:
            print(compat_str)
        self.i2c = create_unified_i2c(bus=bus, freq=freq, sda=sda, scl=scl)
        self.addr = addr

    def read(self):
        self.i2c.writeto_mem(self.addr, 0, bytes([0xAA,0x00,0x00]))
        sleep_ms(10)
       
        status = self.i2c.readfrom_mem(self.addr, 0, 1)
        while((status & BUSY_FLAG) && (status != 0xFF))
            sleep_ms(1)
            status = self.i2c.readfrom_mem(self.addr, 0, 1)

        data = self.i2c.readfrom_mem(self.addr, 0, 4)

        status = data[0]
        if((status & INTEGRITY_FLAG) || (status & MATH_SAT_FLAG))
            return NAN;
        reading = data[1]<<8 & data[2]<<8 & data[3]
        pressure = (reading - OUTPUT_MIN) * (MAXIMUM_PSI - MINIMUM_PSI)
        pressure = (pressure / (OUTPUT_MAX - OUTPUT_MIN)) + MINIMUM_PSI

        return pressure
6 Likes

Wow! Thank you Jim…

My coding experience is from Microcontroller assembler and C for 8-bit and 16-bit devices – i.e. based on registers, port addresses, if-then-else & case structures with loops and subroutine calls.

I started to learn Python when the pi-pico was launched back in January, but have yet to get my head around classes and methods as until now I have never needed to use them. I must admit so far I have yet to get to the a-ha moment as to what is going on. :thinking:

So, again, Thank You!

I am also waiting for the parts to be delivered - hopefully in the next few days.

I will probably try using the Arduino SparkFun code first to check out how the device behaves, and then shift to Python.

Best wishes,

Victor

6 Likes

Hi Jim,

The SparkFun MPR sensors have arrived.

Tested one using an Arduino UNO - Works fine

Moved to Pico - Running a I2C Scan script sees the sensor with address 0x18

Unfortunately main sensor read script produces an error message within the Piicodev_MPR device driver module


I guess we will have to wait until you get a sensor.

Regards,

Victor

PS Lines 42 “while((status…” and 49 “if((status…” needed syntax fixes from your code post

3 Likes

Yep, a few syntax errors, hangover from Ardunio and C++. Didn’t do a lot of checking, was just an example of how it might look.

Able to run the code on a Windows PC & Thonny up to the point where it wants os.uname, apparently that does not work on Windows. There is a work around but it means changing the libraries too much and I am only using the PC as an IDE interface.

Setup the code on a Pi Zero W; ran ok to point where it wants to talk to the Micro Sensor and it gets an IO Error, as expected, no sensor connected.

Considered setting up an Arduino to emulate the Micro Sensor, but might be faster to just get one from Core Electronics. Deliveries are pretty quick at the moment. Usually like to buy more than $100 to spread the cost of postage. Now let me see what other toys I can buy without the missus knowing, LOL

Examining the screen shots you have provided, the code has failed at a strange point. The instruction prior to the while statement is exactly the same. That should have failed as well. Python just steps through the code, no compiler phase.

Also the error message is interesting.
Image1
Sometimes the error messages are a little cryptic, maybe not for an experienced programmer. But it sometimes takes me a while to understand.

I note that the run line (%Run -c $EDITOR_CONTENT) looks like Thonny is running the file from the editor not the file on the Pico. When I get the same run line from Thonny, it means I am trying to run the code from the PC file not the Pi Zero file. If I load the Pi Zero file it then runs ok, showing the name of the file. Unsure if this it an issue with the Pico. Haven’t played with one yet.

Anyway, better get that order off to Core, “keep them guys off the street, haha”.

Cheers
Jim

4 Likes

An I2C multiplexer is the usual workaround for devices with a fixed address

6 Likes

Thank you Jim,

I will check my Thonny setup with a script that has previously run OK on the target Pico.

Swapping between Arduino/C++ and Pico/MicroPython often needs a break to clear ones head – especially when covering new areas in both environments for the first time…
So easy to go down a rabbit hole and not realise it.

keep them guys off the street, haha”… I don’t think the amazing Core team have time to “get out on the streets” the rate that they are pushing out new products, and videos, and tutorials, and…

Best Wishes,

Victor

4 Likes

OK - Have done a sanity check.

Added Pin 25 LED toggle as a way of checking if things are running on target…
Get error message as previously
Comment out MPR sensor lines
LED then toggles… :thinking: :disappointed:

4 Likes

Sensor is on the way, expect early next week.
The way the Pico works is different from the Pi, as I understand it, so the message is most likely ok.
I have two development boards setup now, one for Pi and one for the Pico, so can test on both.

In the mean time I will power up the Pico to get some idea of how it works. Might give me a clue to what is happening. My current project is nearing completion, so need something else to move on to, LOL

Cheers
Jim
PS will get it working, eventually.

5 Likes

The good thing about the CE Unified device driver is that it auto detects the platform (Pi - Pico - Micro:bit) so if the middle layer driver (in our case PiicoDev_MPR) works, then the top layer main.py should be completely portable between platforms.

I am begining to think the error in PiicoDev_MPR is that there is a miss-match to the types used within Unified that presents data at the machine level to devices. I think I need to learn more about classes etc. to get a better understanding.

Best Wishes.

Victor

4 Likes

@Victor153764
Got my Pi Pico working and see that most of my concern about the error message was over my lack of experience using a Pi Pico.

Looking more closely at the way Python works and the existing PiicoDev libraries, I think I made a type definition mistake. Which is really what the error message is saying.

This statement writes to an I2C address, 3 bytes. Which starts the Mico Pressure sensor operating.
self.i2c.writeto_mem(self.addr, 0, bytes([0xAA,0x00,0x00]))

The 2nd parameter in the command is a register specification. I left it as zero as the Micro Pressure sensor has no registers. But some of the other PiicoDev libraries predefined it as a byte.

In C++ you have to define variable types before you use them or as you use them.
Python tries to determine what type you want and assigns it.
Using ‘0’ I think Python is defining the parameter as an integer not a byte.

I wonder if simply changing it to ‘0x00’ would fix it. Python would then see it is a byte.

Regards
Jim

Modified code.

"""
Honeywell Micro Pressure Sensor - MPR
Device in Standby Mode normally, send command, device enters Operating Mode, sensors pressure, when done flags EOC pin and Status byte.

Send 0xAA 0x00 0x00 to start reading.
Wait for status or EOC pin or at least 5ms.
Read 4 bytes, status, data 24:16, data 15:8, data 7:0

"""
from PiicoDev_Unified import *

compat_str = '\nUnified PiicoDev library out of date.  Get the latest module: https://piico.dev/unified \n'

_MPR = 0x18
MAXIMUM_PSI = 25
MINIMUM_PSI = 0

BUSY_FLAG = 0x20
INTEGRITY_FLAG = 0x04
MATH_SAT_FLAG = 0x01

OUTPUT_MAX = 0xE66666
OUTPUT_MIN = 0x19999A

class PiicoDev_MPR(object):     
    def __init__(self, bus=None, freq=None, sda=None, scl=None, addr=_MPR):
        try:
            if compat_ind >= 1:
                pass
            else:
                print(compat_str)
        except:
            print(compat_str)
        self.i2c = create_unified_i2c(bus=bus, freq=freq, sda=sda, scl=scl)
        self.addr = addr

    def read(self):
        self.i2c.writeto_mem(self.addr, 0x00, bytes([0xAA,0x00,0x00]))
        sleep_ms(10)
       
        status = self.i2c.readfrom_mem(self.addr, 0x00, 1)
        while ((status & BUSY_FLAG) and (status != 0xFF)):
            sleep_ms(1)
            status = self.i2c.readfrom_mem(self.addr, 0x00, 1)

        data = self.i2c.readfrom_mem(self.addr, 0x00, 4)

        status = data[0]
        if((status & INTEGRITY_FLAG) or (status & MATH_SAT_FLAG)):
            return NAN;
        reading = data[1]<<8 & data[2]<<8 & data[3]
        pressure = (reading - OUTPUT_MIN) * (MAXIMUM_PSI - MINIMUM_PSI)
        pressure = (pressure / (OUTPUT_MAX - OUTPUT_MIN)) + MINIMUM_PSI

        return pressure


"""
4 Likes

@James46717
Tried Version 3 – unfortunately returns same error

Looking at the datasheet there appears to be a problem with bit checking using bitwise operator " and" within the returned status value (byte, byte array, integer mismatch?)

I have no prior experience in this area of Python so can’t suggest anything I am afraid.

Also noticed on the data sheet (6.4) about each byte for the pressure value requiring an acknowledge from the Pico back to the sensor… not sure if this is already part of piicodev_unified, but I guess we will find out when we get to the next lines of code.

Regards,

Victor

Here is the main.py I have been using

# PiicoDev test script for SparkFun MicroPressure Sensor 10/Dec/2021
# Ported to Python Core-Electronics.au forums James46717 Victor153764

from PiicoDev_MPR import PiicoDev_MPR
from PiicoDev_Unified import sleep_ms # cross-platform compatible sleep function
from machine import Pin

led = Pin(25, Pin.OUT) # check that we are working on the pico
led.on()
sensor = PiicoDev_MPR() # initialise the sensor
print("Piicodev_MPR on pi-pico")

while True:
    # Print data
    pessure = sensor.read() # read all data from the sensor
#     print("MPR Pessure =", pressure)
    sleep_ms(1000)
    led.toggle()

1 Like

Decided that the “While” statement had too much compound behaviour,
So split out the various operations…

… where it appears that we do return from reading the sensor, and there is a problem between types with “status” “BUSY_FLAG” and the “&” operator.

Then added a print statement to see what value “status” had…

… which gives a different error message…

so it may be that “all” we have to do is add some casting functions to fix the problem.

Regards,

Victor

2 Likes

Me Again…

Had the random thought that maybe Adafruit had a “me too” with the pressure sensor… :thinking:

Adafruit MPRLS Ported Pressure Sensor Breakout - 0 to 25 PSI

And they have both GitHub downloads for Arduino and CircuitPython

[Later Edit: adafruit_mprls.py could be of use ]

1 Like

Good work !!!
This is exactly what I would be doing if I had a device to play with and will be doing when it arrives early next week (I hope).

Pretty sure all that is handled by lower level routines in the smbus2 library
(standard library to use with I2C communications, piicodev_unified imports that library).

From what you have done the problem is not in the readfrom_mem function but in use of byte and int even through the error pointed to that line. The BUSY_FLAG and reading of status in the while statement was just a copy of what was done in the Arduino C++ code.

My guess.
The last error is because readfrom_mem() returns a list of bytes (in this case only 1) and print is looking for integers. You could try, print("status" ",hex(status[0]))

I tried to simulate the error, it says list instead of bytes, but close.

Agree, from your testing, reading the sensor is working ok, it is how the results are being handled.

Will definately have a look at that.

Cheers
Jim

2 Likes

Thought I better stop using PiicoDev that is owned by Core electronics.
It was originally just an example.
Shamelessly used the Adafruit code to check status and bits.
Code below. It uses too many variables and could be tidied up. But development …

"""
Honeywell Micro Pressure Sensor - MPR
Device in Standby Mode normally, send command, device enters Operating Mode, sensors pressure, when done flags EOC pin and Status byte.

Send 0xAA 0x00 0x00 to start reading.
Wait for status or EOC pin or at least 5ms.
Read 4 bytes, status, data 24:16, data 15:8, data 7:0
"""

from PiicoDev_Unified import *

compat_str = '\nUnified PiicoDev library out of date.  Get the latest module: https://piico.dev/unified \n'

_MPR = 0x18
MAXIMUM_PSI = 25
MINIMUM_PSI = 0

OUTPUT_MAX = 0xE66666
OUTPUT_MIN = 0x19999A

class Honeywell_MPR(object):     
    def __init__(self, bus=None, freq=None, sda=None, scl=None, addr=_MPR):
        try:
            if compat_ind >= 1:
                pass
            else:
                print(compat_str)
        except:
            print(compat_str)
        self.i2c = create_unified_i2c(bus=bus, freq=freq, sda=sda, scl=scl)
        self.addr = addr

    def read(self):
        self.i2c.writeto_mem(self.addr, 0x00, bytes([0xAA,0x00,0x00]))
        sleep_ms(10)
       
        while True:
            status = self.i2c.readfrom_mem(self.addr, 0x00, 1)
            sleep_ms(1)
            if not status[0] & 0x20:
                break

        data = self.i2c.readfrom_mem(self.addr, 0x00, 4)
        if data[0] & 0x01:
            raise RuntimeError("Internal math saturation")
        if data[0] & 0x04:
            raise RuntimeError("Integrity failure")

        reading = data[1] << 16 | data[2] << 8 | data[3]
        pressure = (reading - OUTPUT_MIN) * (MAXIMUM_PSI - MINIMUM_PSI)
        pressure = (pressure / (OUTPUT_MAX - OUTPUT_MIN)) + MINIMUM_PSI

        return pressure
from Honeywell_MPR import Honeywell_MPR
from PiicoDev_Unified import sleep_ms

sensor = Honeywell_MPR()

while True:
    pressure = sensor.read()
    print(str(pressure))
    sleep_ms(5000)
2 Likes