From 9950f5c2f732b4d5271da7826d37d07239949650 Mon Sep 17 00:00:00 2001 From: Totoo Date: Mon, 7 Oct 2024 15:12:06 +0200 Subject: [PATCH] Updated I2C external device driver integration (markdown) --- I2C-external-device-driver-integration.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/I2C-external-device-driver-integration.md b/I2C-external-device-driver-integration.md index 51e234f..1a17e76 100644 --- a/I2C-external-device-driver-integration.md +++ b/I2C-external-device-driver-integration.md @@ -1,7 +1,7 @@ # I2C external device driver integration > [!IMPORTANT] -Allways check the wiring, because you can kill your devices! +Always check the wiring, because you can kill your devices! ## How the I2CManager works On boot, the system will do a full I2C bus scan, and try to find each device it's driver. If a driver is not found, it won't look for it again. The scan is repeated only on main screen and by any app that requests it. If your app requires the periodical scan for new devices you can enable it but disable it in the destructor! These scans will detect new devices and device removals. Devices will be removed when the I2C communication to it's address fails multiple times in a row. If the device is removed, but found again (like plugged in again) the driver will be started again for it. @@ -19,8 +19,8 @@ Important files: 2. Insert a new enum element into the i2cdevlist.hpp at the END of the enum I2C_DEVMDL. Also create define for the dev's I2C address (for all if it has multiple). This should be I2CDEV_EXAMPLEDEV_ADDR_1 , I2CDEV_EXAMPLEDEV_ADDR_2, ... 3. Create the new i2cdev_exampledev.hpp and i2cdev_exampledev.cpp files. Use the namespace i2cdev! 4. Create the class for the device named I2cDev_ExampleDev, and derive it from I2cDev. -5. Override the bool init(uint8_t addr) function. This function must check the address it got if the module uses it. If yes, then try to init the device. Query for any special registers that you can identify the dev, to make sure it is THAT device you are writing the driver for (since differnet devices share the same address sometimes). If THAT is your device, then set it up and get it ready to go. Also you must return true if the driver is ok. If there is ANY error, you must return false. In this function you MUST set the variable addr to the given address (addr = addr_;). You MUST set the model variable to the new enum you just created. Also you need to set the query_interval value, how often does your device needs to be polled for new data. Don't put here too small value, since it'll slow down the whole system. The value is in seconds. You can use the I2cDev::i2c_read() and i2c_write() functions or one of the helper functions to read / write from the bus. init() must be as fast as possible. -6. Override the void update() function. Here you query your device for new data. If you got any valud, then you broadcast it system wide. (see next step). update() must be as fast as possible. Try not to delay there. So please don't run calibration code that took 1000 samples and 10 seconds. +5. Override the bool init(uint8_t addr) function. This function must check the address it got if the module uses it. If yes, then try to init the device. Query for any special registers that you can identify the dev, to make sure it is THAT device you are writing the driver for (since different devices share the same address sometimes). If THAT is your device, then set it up and get it ready to go. Also you must return true if the driver is ok. If there is ANY error, you must return false. In this function you MUST set the variable addr to the given address (addr = addr_;). You MUST set the model variable to the new enum you just created. Also you need to set the query_interval value, how often does your device needs to be polled for new data. Don't put here too small value, since it'll slow down the whole system. The value is in seconds. You can use the I2cDev::i2c_read() and i2c_write() functions or one of the helper functions to read / write from the bus. init() must be as fast as possible. +6. Override the void update() function. Here you query your device for new data. If you got any value, then you broadcast it system wide. (see next step). update() must be as fast as possible. Try not to delay there. So please don't run calibration code that took 1000 samples and 10 seconds. 7. Select the message you want to use. The current system wide messages are in the message.hpp. If you don't find any that fits your need, you can create a new one. (try to avoid that). 8. In your update() code just create a new message variable you have selected, take for example the EnvironmentDataMessage msg{temp, hum, pressure}; fill it with your data, and send it to the system with the EventDispatcher::send_message(msg); function. 9. Include your hpp file (i2cdev_exampledev.hpp) in the i2cdevmanager.cpp. Then add it to the found() function. There check if the currently found device's address matches any you can handle, and it yes, create an instance of your class (item.dev = std::make_unique()) , and try to call init(). If it fails, set the item.dev = nullptr so other drivers can try to work with it. @@ -33,7 +33,7 @@ You can use the Debug / ExtSensor app to see what I2C devices are found by the s ## App development for devices I2CDevManager::manual_scan() will start an one time scan for new (or removed) devices. -I2CDevManager::set_autoscan_interval() will start a periodic search for new devices. DONT FORGET TO SET IT TO 0 when you finished or your app is closed! +I2CDevManager::set_autoscan_interval() will start a periodic search for new devices. DON'T FORGET TO SET IT TO 0 when you finished or your app is closed! I2CDevManager::get_dev_by_addr(), I2CDevManager::get_dev_by_model() will give you a pointer to the device. Preferred to use the get_dev_by_model(), since with that you'll know what that pointer needs to be casted (it'll return a generic I2cDev, that you derived your driver from). I2CDevManager::get_dev_list_by_model() and I2CDevManager::get_gev_list_by_addr() returns a vector of the models it discovered (that HAS WORKING DRIVER) and all the addresses it sees on the bus (even those without a driver). When the scan detects any change in the device list it'll send a "I2CDevListChangedMessage" system wide message.