Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add I2C DHT12 sensor #124

Merged
merged 22 commits into from
Feb 28, 2020
Merged

Add I2C DHT12 sensor #124

merged 22 commits into from
Feb 28, 2020

Conversation

enelson1001
Copy link
Contributor

Please review adding i2c DHT12 sensor

@PerMalmberg
Copy link
Owner

Very neat, and so little code needed for another device. 👍

Could you please update the contributions file naming yourself and linking this PR? Also, please add this device to the readme in the project root.

Do you have more changes coming?

@enelson1001
Copy link
Contributor Author

  1. Will update contributors.md file.
  2. Will update readme.md file
  3. Will add datasheet to Documents folder.
  4. I have written a driver for the SH1107 display used on the M5Stick-Mono version and I am currently working on the driver for the ST7735S that is used on the M5StickC. I thought I would submit both of these at the same time when they were done. On the SH1107 driver I can't see how to create a test code since the chip does not support reporting an ID when using SPI.
    4a. Will there be a problem if no test code is provided?
    4b. Is it OK to create a new PR for these two displays or do you want to add the displays to this PR?
  5. I have a couple of questions for you in the next two comments (hope you don't mind)

@enelson1001
Copy link
Contributor Author

Question 1
I have been running my application M5StackBME280 as seen on my github page. In the code I print out the Systems Stats every couple of seconds. Below is what I have captured. My question: Is it normal for Main task to keep growing (ie use more memory)? To me it looks like the App will eventually run out of memory? Am I correct in thinking that LittlevGL is not the problem since its stack size is not changing?

=================================================================================================
Jan 4 - using malloc and free in littlevgl
=================================================================================================
I (4755) SocketDispatcher: Network up, sockets will be restarted.
W (10773) APP: ============ Main TICK TICK TICK  =============
I (10774) MemStat: Mem type |  8-bit free | Smallest block | Minimum free | 32-bit free | Smallest block | Minimum free
I (10781) MemStat: INTERNAL |      107812 |          88200 |        97460 |      158656 |          88200 |       148296
I (10792) MemStat:      DMA |      107812 |          88200 |        97460 |      107812 |          88200 |        97460
I (10803) MemStat:   SPIRAM |           0 |              0 |            0 |           0 |              0 |            0
I (10815) MemStat: 
I (10819) MemStat:             Name |      Stack |  Min free stack |  Max used stack
I (10826) MemStat:         LvglTask |       4096 |             560 |            3536
I (10834) MemStat:         SntpTask |       3200 |             772 |            2428
I (10843) MemStat:   PollSensorTask |       3300 |             484 |            2816
I (10851) MemStat: SocketDispatcher |      20480 |           18392 |            2088
I (10859) MemStat:         MainTask |      16384 |           13308 |            3076


W (81440) APP: ============ Main TICK TICK TICK  =============
I (81441) MemStat: Mem type |  8-bit free | Smallest block | Minimum free | 32-bit free | Smallest block | Minimum free
I (81448) MemStat: INTERNAL |      107504 |          88200 |        97120 |      158348 |          88200 |       147956
I (81459) MemStat:      DMA |      107504 |          88200 |        97120 |      107504 |          88200 |        97120
I (81471) MemStat:   SPIRAM |           0 |              0 |            0 |           0 |              0 |            0
I (81482) MemStat: 
I (81485) MemStat:             Name |      Stack |  Min free stack |  Max used stack
I (81493) MemStat:         LvglTask |       4096 |             560 |            3536
I (81502) MemStat:         SntpTask |       3200 |             772 |            2428
I (81510) MemStat:   PollSensorTask |       3300 |             484 |            2816
I (81519) MemStat: SocketDispatcher |      20480 |           18216 |            2264
I (81527) MemStat:         MainTask |      16384 |           12588 |            3796

W (2040282) APP: ============ Main TICK TICK TICK  =============
I (2040283) MemStat: Mem type |  8-bit free | Smallest block | Minimum free | 32-bit free | Smallest block | Minimum free
I (2040290) MemStat: INTERNAL |      107448 |          88200 |        77764 |      158292 |          88200 |       128600
I (2040302) MemStat:      DMA |      107448 |          88200 |        77764 |      107448 |          88200 |        77764
I (2040313) MemStat:   SPIRAM |           0 |              0 |            0 |           0 |              0 |            0
I (2040325) MemStat: 
I (2040328) MemStat:             Name |      Stack |  Min free stack |  Max used stack
I (2040336) MemStat:         LvglTask |       4096 |             560 |            3536
I (2040345) MemStat:         SntpTask |       3200 |             772 |            2428
I (2040353) MemStat:   PollSensorTask |       3300 |             476 |            2824
I (2040362) MemStat: SocketDispatcher |      20480 |           18216 |            2264
I (2040371) MemStat:         MainTask |      16384 |           12524 |            3860

W (3948752) APP: ============ Main TICK TICK TICK  =============
I (3948754) MemStat: Mem type |  8-bit free | Smallest block | Minimum free | 32-bit free | Smallest block | Minimum free
I (3948761) MemStat: INTERNAL |      107332 |          88200 |        77704 |      158176 |          88200 |       128540
I (3948772) MemStat:      DMA |      107332 |          88200 |        77704 |      107332 |          88200 |        77704
I (3948783) MemStat:   SPIRAM |           0 |              0 |            0 |           0 |              0 |            0
I (3948795) MemStat: 
I (3948798) MemStat:             Name |      Stack |  Min free stack |  Max used stack
I (3948807) MemStat:         LvglTask |       4096 |             560 |            3536
I (3948816) MemStat:         SntpTask |       3200 |             772 |            2428
I (3948824) MemStat:   PollSensorTask |       3300 |             476 |            2824
I (3948832) MemStat: SocketDispatcher |      20480 |           18216 |            2264
I (3948841) MemStat:         MainTask |      16384 |           12508 |            3876

W (8684584) APP: ============ Main TICK TICK TICK  =============
I (8684585) MemStat: Mem type |  8-bit free | Smallest block | Minimum free | 32-bit free | Smallest block | Minimum free
I (8684592) MemStat: INTERNAL |      107324 |          88200 |        75800 |      158168 |          88200 |       126636
I (8684604) MemStat:      DMA |      107324 |          88200 |        75800 |      107324 |          88200 |        75800
I (8684615) MemStat:   SPIRAM |           0 |              0 |            0 |           0 |              0 |            0
I (8684627) MemStat: 
I (8684630) MemStat:             Name |      Stack |  Min free stack |  Max used stack
I (8684638) MemStat:         LvglTask |       4096 |             560 |            3536
I (8684647) MemStat:         SntpTask |       3200 |             772 |            2428
I (8684655) MemStat:   PollSensorTask |       3300 |             476 |            2824
I (8684664) MemStat: SocketDispatcher |      20480 |           18216 |            2264
I (8684673) MemStat:         MainTask |      16384 |           12508 |            3876

W (19560761) APP: ============ Main TICK TICK TICK  =============
I (19560762) MemStat: Mem type |  8-bit free | Smallest block | Minimum free | 32-bit free | Smallest block | Minimum free
I (19560770) MemStat: INTERNAL |      107120 |          88200 |        76388 |      157964 |          88200 |       127224
I (19560782) MemStat:      DMA |      107120 |          88200 |        76388 |      107120 |          88200 |        76388
I (19560793) MemStat:   SPIRAM |           0 |              0 |            0 |           0 |              0 |            0
I (19560804) MemStat: 
I (19560808) MemStat:             Name |      Stack |  Min free stack |  Max used stack
I (19560817) MemStat:         LvglTask |       4096 |             560 |            3536
I (19560825) MemStat:         SntpTask |       3200 |             772 |            2428
I (19560834) MemStat:   PollSensorTask |       3300 |             476 |            2824
I (19560842) MemStat: SocketDispatcher |      20480 |           18216 |            2264
I (19560851) MemStat:         MainTask |      16384 |           12476 |            3908

@enelson1001
Copy link
Contributor Author

Question 2
LittlevGL requires the DisplayDriver to call lv_tick_inc(num_of_milliseconds). In the Display driver code I have accomplished this by using the following code.

esp_register_freertos_tick_hook(lv_tick_task);  // Inside bool DisplayDriver::initialize()

and

// The  lv_tick_task that is required by LittlevGL for internal timing
void IRAM_ATTR DisplayDriver::lv_tick_task(void)
{
        lv_tick_inc(portTICK_RATE_MS);  // 1 ms tick_task
}

On the M5StackDHT12 App I have written but not yet pushed to my git hub, I eliminated
esp_register_freertos_tick_hook(lv_tick_task); and used the Smooth TimerExpiredEvent but this increased code size by 10Kbytes.

Inside - bool DisplayDriver::initialize()
tick = Timer::create(1, timer_expired_event, true, milliseconds{5});
tick->start();

and
void DisplayDriver::event(const smooth::core::timer::TimerExpiredEvent& event)
{
        lv_tick_inc(5);  // 5 ms tick_task
}
  1. My question: Is it OK to use esp_register_freertos_tick_hook(lv_tick_task); with Smooth without having some problems. Right now the code runs OK with no problems but wanted to make sure no gotchas in doing so.
  2. The M5StackDHT12 App using the Smooth TimerExpiredEvent also has the same problem were the MainTask keeps growing and the Internal Memory decreases.

@PerMalmberg
Copy link
Owner

  1. If memory keeps going down you have a memory leak.

  2. The code increase is likely due to that you're now using the timer system. The original lv_tick_task has the IRAM_ATTR. If there's no requirement for that, then calling it via a TimerEvent isn't different from calling it from elsewhere; the TimerTick is run from within the Task that started the Tick.

@enelson1001
Copy link
Contributor Author

From previous questions and your response.

  1. Memory finally stabilized but took a very very long time (24 hrs).
  2. My DisplayDriver is now using IRAM_ATTR lv_tick_task() and esp_register_freertos_tick_hook(lv_tick_task) and not a seperate TimerTick task. Everything is working OK.

I thought I would give you an update on my progress. I have successfully been able to write to the ST7735S display on the M5StickC. I have changed the name of the ILI9341.cpp and ILI9341.h to LcdSpi.cpp and LcdSpi.h since both the ILI9341 and the ST7735 can use the same code. The only thing that is different is the initialization commands. I removed the back-light pin since the ST7735 on the M5StickC uses a power management IC to control back-lighting. I do back-lighting settings in the next level up code which I call DisplayDriver.

I have written code for the I2C-AXP192 power management IC because I needed it to be able to get the M5Stick to power up properly (and power the ST7735s chip) but I need to do some more testing.

The M5Stick also has an I2C RTC - BM8563 which I plan on writing the I2C code for it. I have not started on this yet but I don't think it will take to long to complete.

I have written separate code for the display chip SH1107 used on the M5StickMono which is working but now I would like to use the LcdSpi. To incorporate the SH1107 into the LcdSpi I would need to add two functions: send_page() and set_common_output_scan_direction() that are only used if you are using the SH1107 and possibly other monochrome displays. It does not use send_lines(). If I don't add these two functions to LcdSpi then I am duplicating code from the LcdSpi in the SH1107.

  1. Is it OK to add send_page() and set_common_output_scan_direction() to LcdSpi?
  2. Is it OK to add all the display changes in my fork for your review now and add the additional I2C drivers to my fork later.

@PerMalmberg
Copy link
Owner

1 Sure, why not?
2. Whichever works for you. I'm pretty busy atm so a review may take some time.

@enelson1001
Copy link
Contributor Author

  1. Great!!!
  2. Since you are busy will dump everything into fork at the same time. May end of next week.

@enelson1001
Copy link
Contributor Author

Summary of display changes

I thought I would submit the display changes now for you review since I am still working on the AXP driver.

1. DisplaySpi.cpp DisplaySpi.h

This was originally called ili9341.cpp. Re-named as this is the core class to use when interfacing to a display. I was going to name it LcdSpi but since there are LCD and OLED displays I decided to make the name more generic. Added preset pin levels for chip select and reset.

1.1 Function - set_madctl()

This function was originally named set_rotation. Re-named to set_madctl because that is what the function is doing. Added a argument to allow user to change the madct register address from the default of 0x36.

1.2 Function - hw_reset()

Added addition arguments active_low, active_time and delay so the function is allows a different active reset state and allows users to fine tune the reset times.

1.3 Function - sw_reset()

Added function to support software reset of display. Some display do not use hardware reset and only have software reset. This function could be called before the init commands are executed.

1.4 Function - send_init_cmds()

This function originally didn't have any arguments. Now we pass in the init_cmds starting address and the length or number of init_cmds so user can specify. Also cleaned up code and added the ability to have a delay when a command has data.

1.5 Function - send_cmds()

This is a new function added. It was added to support the monochrome display. This function is more efficient the doing multiple send_cmd.

1.6 Function - send_cmd()

This function was originally named lcd_wr_cmd. Wanted to get away from having "lcd" in the name. The name "send" was being used so decided all write functions would have the name send.

1.7 Function - send_data()

This function was originally name lcd_wr_data.

1.8 Function - set_back_light()

This function was removed and performed by the next level up from DisplaySpi. Some display do not control back-lighting via a GPIO pin. The M5StickC using the AXP192 power management IC to set the output voltage on an LDO to control the back-lighting. Some displays may use a PWM signal.

2.1 DisplayTypes.h

A header file that contains custom typedef used on DisplaySpi.

3.1 DisplayCommands.h

A header file that contain the most common LCD commands. New commands required for different displays should be included in their "MyNewDisplay.h" file.

4.1 IlI9341.h

A header file that contains information pertaining to the ILI9341. In this case it only contains vector<display_int_cmd_t> of initialization commands.

5.1 ST7735.h

A header file that contains some unique init_cmds for various ST7735 models and some unique CGRAM offsets for various ST7735 models.

6.1 SH1107.h

A header file that contains unique commands for the SH1107, the init_cmds.

7.1 Smooth/test/spi_4_line_devices_test.cpp .h

Modified to use DisplaySpi instead of ILI9341 and removed enabling back-light.

Reset discussion

Some displays do not use a reset pin and tie the pin HIGH. This saves them on not have to use a gpio pin and instead use sw_reset. I could not find a way to pass GPIO_NUM_NC for reset. Is there a way to pass GPIO_NUM_NC or should the reset function be removed from DisplaySPI like back-lighting?

My progress

The AXP driver is taking a lot more time then I anticipated, partially because I am doing it for AXP192, AXP173 and AXP202 chips. There are a lot of registers and lot of functionality in each register. The code will be large so I will eventually submit but I would understand if you did not want to add an I2C driver that is well over 1500 lines.
I have not started on the I2C RTC chip.

@PerMalmberg
Copy link
Owner

I left a few comments, but overall it looks really good.

Some displays do not use a reset pin and tie the pin HIGH. This saves them on not have to use a gpio pin and instead use sw_reset. I could not find a way to pass GPIO_NUM_NC for reset. Is there a way to pass GPIO_NUM_NC or should the reset function be removed from DisplaySPI like back-lighting?

I don't understand what it is you want to do? If they tie a pin high, they're not saving a GPIO, are they? Or do you mean they tie it high on the display side, that'd save a pin on the MCU.

@enelson1001
Copy link
Contributor Author

Yes this is what I mean - they tie the reset pin high on the display side and that saves a pin on the MCU side.
I am kinda leaning on removing the reset pin from DisplaySPI and therefore removing the hw_reset function().

@PerMalmberg
Copy link
Owner

From an API standpoint it's nice to provide the reset-functionality. Optimally it should be agnostic, i.e. don't care what the actual implementation is, i.e. h/w or s/w. Another way to implement it is to template the driver such that you do DispalySPI or DisplaySPI. This would make the class oblivious to the actual implementation of the reset functionality.

Don't you ever call the reset from within the class?

@PerMalmberg
Copy link
Owner

Have you pushed the latest changes, I can't see them in this PR?

@enelson1001
Copy link
Contributor Author

Yes I have pushed and see the changes in my fork.

@enelson1001
Copy link
Contributor Author

You said
From an API standpoint it's nice to provide the reset-functionality. Optimally it should be agnostic, i.e. don't care what the actual implementation is, i.e. h/w or s/w. Another way to implement it is to template the driver such that you do DispalySPI or DisplaySPI. This would make the class oblivious to the actual implementation of the reset functionality.

Don't you ever call the reset from within the class?

  1. I am not sure how to use templates that would allow the user to use only 2 smooth::core:io:Ouput (cs, dc) and not use (reset) smooth::core::io::Output.
  2. I never call reset (sw_reset or hw_reset) within the class that is up to the user to decide which one to use.
  3. An example of a display that would not require a gpio pin for reset. In the schematic you can see they use the AXP803 to perform the resetting of the tft display. https://learn.adafruit.com/adafruit-2-4-tft-touch-screen-featherwing/downloads

@PerMalmberg
Copy link
Owner

Odd, I see the changes in your master, but not in this PR which references your master.

Anyway, changes looks good. Re. reset, do what you feel is best.

@enelson1001
Copy link
Contributor Author

The new code uploaded allows the user to add a reset pin and a a backlight pin. I also put back in the set_back_light(). The spi_4_line_devices_test.cpp shows how to add for example the reset pin. If you do not like this approach I can revert back to the previous code or modify if you have some changes.

@PerMalmberg
Copy link
Owner

The approach itself isn't bad, though for the sake of keeping memory usage low, I suggest using a fixed array with constants to index into the array to get the desired pin instead of the dynamically allocating hash-table.

@enelson1001
Copy link
Contributor Author

Added AxpPMU as a generic way to handle the AXP173, AXP192 and AXP202. I didn't like the idea of having 3000 lines of code to read and write every little detail on all the registers on the AXP. Almost all the registers are used to configuring the chip so took the approach that the lcd displays used and created a function - write_int_regs() that would be used to write a bunch of registers to configure the chip. The user will create this file since it is product dependent meaning I can't create for example an AXP192InitCmd.h file because one product may program the LDO or DC-DC power supplies to a different voltage. I made some functions virtual so user could inherit the AxpPMU and override these functions (some device does not support the get_gpioX_voltage) and possibly log an error.
I also added more pdf files for displays and AXP devices. I will start on the RTC next.

Copy link
Owner

@PerMalmberg PerMalmberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very clean. Well done.

I think it would be beneficial to have your comments about how to use this class documented in a README-AXP.md, especially if it it doesn't make sense to create a test/example project for this class.

@enelson1001
Copy link
Contributor Author

I will create README-AXP.md and submit updates soon

@enelson1001
Copy link
Contributor Author

I won't be added anymore devices (maybe a couple more but that will be a few months from now) and think I have made all the changes you requested for AxpPMU and DisplaySPI. I wasn't sure where to place the README-AXP file so I just put in Documents. I assume one more round of changes for the RTC and hopefully you can push to your branch so I can update my projects. I have to say I am impressed with how much functionality I can get using Smooth and LvGL on a ESP32 with and LCD display.

@PerMalmberg
Copy link
Owner

PerMalmberg commented Feb 28, 2020

I assume one more round of changes for the RTC

Just a small comment, looks fine otherwise.

I have to say I am impressed with how much functionality I can get using Smooth and LvGL on a ESP32 with and LCD display.

Me too, I never thought it'd be so useful for anyone else. I'm a bit surprised that you've not found any bugs, considering that entire Smooth (well, almost now) has been a one-man project. Sure, I've put in a lot of effort into it but still... It makes me happy to see it being used.

Would love to see a video or something of what you're building.

@PerMalmberg PerMalmberg merged commit b4bf80b into PerMalmberg:master Feb 28, 2020
@PerMalmberg
Copy link
Owner

Merged and done. Awesome work, @enelson1001

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants