Is my tile36 missing something or is this code sketchy

The official PYBD running MicroPython, and its accessories.
Target audience: Users with a PYBD
Post Reply
rhubarbdog
Posts: 168
Joined: Tue Nov 07, 2017 11:45 pm

Is my tile36 missing something or is this code sketchy

Post by rhubarbdog » Fri May 24, 2019 10:56 am

I've just got my pyboard d and tile36.

I go to the code examples
I copy and paste it to a file add the lines

Code: Select all

set_i2caddr()
random_dots(dt=300)
I get the output

Code: Select all

Traceback (most recent call last):
  File "<stdin>", line 151, in <module>
  File "<stdin>", line 39, in set_i2caddr
  File "<stdin>", line 32, in save_nvram
OSError: [Errno 19] ENODEV
it makes references to (non voaltile) nvram but I have none.
I have tested my tile with

Code: Select all

random_dots(dt=300, addr = LED_ADDR)
but to get the rest of the examples working requires quite a bit of work or I need more hardware for this to work as intended.

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Is my tile36 missing something or is this code sketchy

Post by jimmo » Fri May 24, 2019 11:09 am

Hey, can you see this thread and see if either thing applies to you viewtopic.php?f=20&t=6272 (WBUS28 vs 68, and setting brightness first).

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Is my tile36 missing something or is this code sketchy

Post by jimmo » Fri May 24, 2019 11:12 am

FYI, the set_i2caddr is if you want to change the configuration of the tile such that it uses a different address (useful if you have multiple). The NVRAM refers to the storage on the chip on the tile that remembers this config.

rhubarbdog
Posts: 168
Joined: Tue Nov 07, 2017 11:45 pm

Re: Is my tile36 missing something or is this code sketchy

Post by rhubarbdog » Fri May 24, 2019 11:25 am

So that nvram should exist on my tile36 allowing me to give the tile an address of something different to 60?

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Is my tile36 missing something or is this code sketchy

Post by jimmo » Fri May 24, 2019 11:51 am

Yup, exactly.

That said... I just looked at this code more closely. The constant at the top does nothing. It would seem that the tile always responds to the address 1 (is this a feature of the firmware on this tile?), but can be configured with a specific address, defaulting to 60.

For some reason the code defaults all methods to using 1. (Would probably be better if the methods were all `def foo(..., addr=LED_ADDR):` )

Note that it appears you have to power cycle the tile to get it to recognise the address change. But I was able to change mine, and it still always responds to 1.

Also, for reasons that aren't clear to me, you still have to set the brightness before you can change the i2c addr?? I haven't read the datasheet in detail yet though.

Code: Select all

>>> led36.set_i2caddr(addr=60, oaddr=70)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "led36.py", line 39, in set_i2caddr
  File "led36.py", line 32, in save_nvram
OSError: [Errno 19] ENODEV
>>> led36.brightness(100)
>>> led36.set_i2caddr(addr=60, oaddr=70)
>>> 

{Edit:

It doesn't appear to be setting the brightness that's important, it's just that there's something about the initialization. The datasheet says "After power up LED36 waits for a SOH character (0x01) to start operation", but setting the brightness doesn't do this. I'm guessing by "All connected LED36 modules can be activated with a single byte sent to the I2C broadcast address 1." that it's literally that it's seeing a 0x01 on the bus, which would be if you were addressing addr=1, (except that would actually be 0b00000010 (7-bit + write)).

I'm also intrigued by "The first tile uses the default address 60, other tiles, currently up to 16, use successive addresses." does that mean that the devices on the same bus are aware of eachother and can automatically sequentially-assign addresses? How does that interact with setting the i2c address manually? Sounds neat though!

}

rhubarbdog
Posts: 168
Joined: Tue Nov 07, 2017 11:45 pm

Re: Is my tile36 missing something or is this code sketchy

Post by rhubarbdog » Fri May 24, 2019 1:52 pm

I've read the docs. The code is sketchy it should read.

Code: Select all

def set_i2caddr(addr=60, oaddr=1):
    """ modify I2C address and save it to NVRAM """
    ba = bytearray(b'\x02\x0eI2C ')
    ba[-1] = (oaddr*2) & 0xfe
    i2c.writeto(addr, ba)
    save_nvram(addr)
The docs are also sketchy
After setting the i2c Address you need to power cycle the tile36 (pyboard) as i2c.scan() before the power cycle is the old address

You don't need to call brightness first, the correct way to wake the device up is

Code: Select all

i2c.writeto(addr, b'\x01')
time.sleep_ms(30)
The sleep isn't in the documentation, but you need it.

Warning, writing b'\x01' at any time after this has special meaning,

Code: Select all

i2c.writeto(addr, b'\x00')
time.sleep_ms(30)
also wakes the device up and is probably safer

Edit,
Note.
It makes sense to set the brightness before changing the address. The current brightness is saved as the default brightness when you use function save_nvram

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Is my tile36 missing something or is this code sketchy

Post by jimmo » Fri May 24, 2019 2:18 pm

rhubarbdog wrote:
Fri May 24, 2019 1:52 pm
I've read the docs. The code is sketchy it should read.

Code: Select all

def set_i2caddr(addr=60, oaddr=1):
    """ modify I2C address and save it to NVRAM """
    ba = bytearray(b'\x02\x0eI2C ')
    ba[-1] = (oaddr*2) & 0xfe
    i2c.writeto(addr, ba)
    save_nvram(addr)
I think the intention in the example code is that "addr" is the new address, and "oaddr" is the old address. I think your change makes sense, but with "oaddr" renamed to "new_addr". (and default addr=1, new_addr=0x60 to be consistent with other methods).
rhubarbdog wrote:
Fri May 24, 2019 1:52 pm
After setting the i2c Address you need to power cycle the tile36 (pyboard) as i2c.scan() before the power cycle is the old address
Not sure what you meant by (pyboard) in parens, but you don't need to power cycle the pyboard. Just toggle the EN_3V3 pin.
rhubarbdog wrote:
Fri May 24, 2019 1:52 pm
You don't need to call brightness first, the correct way to wake the device up is

Code: Select all

i2c.writeto(addr, b'\x01')
time.sleep_ms(30)
The sleep isn't in the documentation, but you need it.
Yeah I realised after sending this that the documentation says 0x01, but actually any value works. (Which is why brightness works).

I'll try and get the docs and the code sample updated. Probably add an init().

Code: Select all

def init(addr=1):
  i2c.writeto(addr, b'\x01')  # Maybe not 0x01 though, like you suggest. Will clarify.
  time.sleep_ms(16)

rhubarbdog
Posts: 168
Joined: Tue Nov 07, 2017 11:45 pm

Re: Is my tile36 missing something or is this code sketchy

Post by rhubarbdog » Fri May 24, 2019 2:38 pm

While your doing that is it worth changing this to read

Code: Select all

def save_nvram(addr):
Writing to nv ram on the broadcast address (1) will update the nvram of all tile36 meaning that any unwanted brightness settings will be recorded for future use

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Is my tile36 missing something or is this code sketchy

Post by jimmo » Fri May 24, 2019 3:29 pm

rhubarbdog wrote:
Fri May 24, 2019 2:38 pm
While your doing that is it worth changing this to read

Code: Select all

def save_nvram(addr):
Writing to nv ram on the broadcast address (1) will update the nvram of all tile36 meaning that any unwanted brightness settings will be recorded for future use
Yeah, good idea!

Post Reply