sde1000 / python-dali

Library for controlling DALI lighting systems
Other
150 stars 73 forks source link

Add support for DiiA extended memory banks #61

Closed ferdinandkeil closed 2 years ago

ferdinandkeil commented 4 years ago

First let me thank you for the great work you have done with this project :+1: . The setup I am planning would not have been possible without it.

I am conducting accelerated life tests of commercial LED drivers as part of my PhD and I want to record the data from the DiiA extended memory banks (e.g. primary side power, secondary side power) during these tests. As my test setup is running on Python I plan on using this library to read those memory banks. I have also build my own (quad) DALI-USB-interface and I will add a driver for that as well.

My question is: what would be a good place to add the support for the extended memory banks? As a new type of gear? I am not certain right now if the extensions only affect LED drivers or other types of drivers as well.

sde1000 commented 4 years ago

I'm glad you find it useful!

The documents I have only describe memory banks 0 and 1. Which memory banks are you going to be accessing? (Are they in the "manufacturer specific" range 2–199, or the "reserved" range 200–255?) Which document defines their contents?

The dali.gear module only describes commands and responses for gear. I think that code for accessing memory locations needs to live in a different part of the library. Perhaps add a new package dali.memory? It isn't clear to me yet how this should be structured; apart from banks 0 and 1 defined in the standard, I don't know how much there is in common between different types of gear from different manufacturers.

When you write the driver for your DALI-USB interface, can I nudge you toward implementing it as an async driver? (See drivers/hid.py for current examples.) I think that will be more generally useful in the future; all the code I'm writing at the moment (a module that polls devices on the bus to convert detected changes of state into events) is only intended to work with async drivers.

ferdinandkeil commented 4 years ago

These memory banks are in the reserved range. Documentation on them can be downloaded from here: https://www.digitalilluminationinterface.org/specifications/download.html

A new module might be a good idea. These memory locations are all accessed using the read memory commands, so no additional commands are needed. However, their interpretation is rather involved (e.g. due to multi-byte values).

I have implemented a transparent translation from UART to DALI, so it should be trivial (fingers crossed :crossed_fingers:) to implement an asynchronous driver using pyserial-asyncio. The firmware for the interface lives here: https://git.rwth-aachen.de/Ferdinand.Keil/efm8-dali-uart-bridge

sde1000 commented 4 years ago

Perhaps write a base class that implements a generic memory bank (a bank number plus data of length 3..255 bytes as specified in byte 0) and a bunch of classes that specialise it with extra attributes for particular bank numbers and knowledge of which parts are read-only and which parts are read-write? It looks like you'll have to support memory locations being unimplemented (reads as "NO" from the device) as well as having a value in the range 0..255.

If you want to support writing to memory banks, get the class to keep a log of what has changed so it can be written back to the device efficiently.

I'd structure the code such that it doesn't care whether a sync or async driver is being used, to make it as generally useful as possible. Perhaps have coroutine-based interfaces for reading and updating memory banks on the device that yields the command it needs executing, and receives the response via .send() on the generator?

ferdinandkeil commented 4 years ago

So that's what I will do. I will keep you posted once I have something working.

Thank you for your advice :+1:

ferdinandkeil commented 4 years ago

I have just pushed a first version of the memory bank support (https://github.com/ferdinandkeil/python-dali/commit/fc27fc528e6b88eef35b5aecd2c62bddf706cb3d). Let me know what you think.

sde1000 commented 4 years ago

I've had a quick look. I haven't been able to try it out yet because my test rig is in pieces!

I like that it's possible to retrieve individual values without reading the whole memory bank, and that you don't need to know which memory bank something is in to read it.

I think there's a lot of redundancy in how you're describing the memory bank contents. It looks like each piece of information is present in the source in (at least?) two places: as a class with an embedded list of locations, and in a list of "what is here?" for each location in a memory bank. It should be possible to generate one from the other at module load time.

ferdinandkeil commented 4 years ago

Thank you for your feedback.

You are correct, but the redundancy was intentional. But after thinking about it some more, I finally removed the memory bank tables. The idea was, that a user could explore the actual layout of the table this way. However, if someone is really that curious about it they can just look it up in the PDF file. I will commit these changes soon.

Testing the code I found that older drivers (old = without D4i support) don't have a lot to say over DALI. So if you want to have a play with it make sure you get one of the most recent drivers.

If you need a DALI adapter for your test setup I can send you one of my quad-DALI-USB interfaces.

sde1000 commented 2 years ago

Memory bank feature now merged!