Skip to content

[P126] Add 74HC595 Shiftregisters plugin#3917

Merged
TD-er merged 34 commits intoletscontrolit:megafrom
tonhuisman:feature/p126-74hc595-shiftregisters
Mar 31, 2022
Merged

[P126] Add 74HC595 Shiftregisters plugin#3917
TD-er merged 34 commits intoletscontrolit:megafrom
tonhuisman:feature/p126-74hc595-shiftregisters

Conversation

@tonhuisman
Copy link
Copy Markdown
Contributor

@tonhuisman tonhuisman commented Jan 16, 2022

On a request from this forum thread

Plugin to control from 1 to 16 255 74HC595 (and compatible) shift-registers, connected in a daisy-chain, as supported by these chips. (More daisy-chained chips can easily be supported, but the state can't be displayed on the Devices page)
Includes an 'un-templated' (to avoid code duplication) version of the Simsso (Timo Denk) ShiftRegister74HC595 library, as that is tried and proven technology.

Available in TEST_E builds.

TODO:

  • Restore state from RTC memory on warm boot. (max. 16 chips * 8 pins can be (re)stored)
  • Documentation
  • Testing (volunteers/help wanted 👍) (confirmed)

Removed from TODO list:

  • Add mapping support/command(s) for 7-segment displays (similar to P073)
  • Testing for 7-segment display (once implemented)

I removed this feature from the TODO list, as further investigation has revealed that most of the 7-segment displays driven by 74HC595 (and compatible) chips, are actually driven in a matrix, requiring continuous updating of the data sent to the shift registers, and while an ESP is perfectly capable of doing that as a single task, it will put too much strain on the ESP for ESPEasy to function as intended and desired, resulting in possibly dropped WiFi connection, and slow response on any other task it has to perform, while the regular tasks & rules processing probably will distort the display.
NB: This plugin can still be used to control a static, 1:1 connected, 74HC595 -> single 7-segment display, as in that case the 8 outputs are then each directly connected to a segment and the decimal point.

If 7-segment displays are desired, please have a look at the TM1637/MAX7219, 4, 6 or 8 digit, 7-segment displays, as supported by P073 - Display - 7-segment display.

…mprove 74hcSetAll for setting multiple output pins
@ghtester
Copy link
Copy Markdown

I am already preparing my environment for tests. I would like to use this shiftregister to control relays that should survive their status (if the shiftregister & plugin works as I assume) over ESP node unexpected reboot when GPIO pins are reset to 0.

@tonhuisman
Copy link
Copy Markdown
Contributor Author

I'm not sure it can work that way, as the current state can't be read from the shiftregisters, it is serial-out only, AFAICS.
May need a set of 74hc165 (not sure I got the right type, the shift-in type) to read the state, but that chip is not supported by ESPEasy (yet).

@ghtester
Copy link
Copy Markdown

ghtester commented Jan 20, 2022

I don't need to read the status, for me it's enough to write the register so 74HC595 should be fine. But I need the shift register output to keep the written status until it's updated with another data (complete 8 bits) . I suppose the outputs are not changing when the serial data are filling the register. And the must is that the outputs are still keeping the last status even though the ESP node is warm rebooted by any reason.

@tonhuisman
Copy link
Copy Markdown
Contributor Author

tonhuisman commented Jan 20, 2022

Well, then that should be covered, as nothing is written to the registers at startup of the plugin, only when using the available commands: (last updated: 2022-02-27)

/** Commands:
 * ShiftOut,Set,<pin>,<0|1>                       : Set a single pin on or off, and update.
 * ShiftOut,SetNoUpdate,<pin>,<0|1>               : Set a single pin on or off. Use ShiftOut,Update to set outputs.
 * ShiftOut,Update                                : Update all pin states to the registers.
 * ShiftOut,SetAll,[chip:][width:]<value>...      : Set a range of chips with values, default 32 bit values (width 4).
 * ShiftOut,SetAllNoUpdate,[chip:][width:]<value> : Ditto, without immediate update. Use ShiftOut,Update to set outputs.
 * ShiftOut,SetAllLow                             : Set all register outputs to 0/low.
 * ShiftOut,SetAllHigh                            : Set all register outputs to 1/high.
 * ShiftOut,SetChipCount,<chip count>             : Set the number of chips, without restarting the plugin. Range 1..P126_MAX_CHIP_COUNT.
 * ShiftOut,SetOffset,<chip offset>               : Set the chip offset for display. Will reflect in device configuration, but not saved.
 * ShiftOut,SetHexBin,<0|1>                       : Turn off/on the Hex or Bin Values display, reflected in device configuration, not saved.
 */

So you can set up separate pins using ShiftOut,SetNoUpdate or groups using the ShiftOut,SetAllNoUpdate commands and then issue a ShiftOutUpdate command to output the state on the pins 😃

Be careful though to not use GPIO pins that change state during startup of the ESP, as that might trigger outputting an unexpected state. See: https://espeasy.readthedocs.io/en/latest/Reference/GPIO.html

@uzi18
Copy link
Copy Markdown
Contributor

uzi18 commented Jan 20, 2022

@tonhuisman @TD-er isn't it more elegant to add setSize(uint8_t nb) method and not resize _digitalValues everytime ?

@tonhuisman
Copy link
Copy Markdown
Contributor Author

not resize _digitalValues everytime

Not sure what you are hinting at here. That vector is sized at initialization, and when setting/clearing all bits, AFAICS.

@ghtester
Copy link
Copy Markdown

ghtester commented Jan 20, 2022

Thanks for the great news. :-)

Be careful though to not use GPIO pins that change state during startup of the ESP, as that might trigger outputting an unexpected state.

Yes that's what I was thinking of as I am already using most of GPIOs and on ESP8266 it's a problem. It will be necessary to decide what to regret (or find a way for sharing some GPIOs).

@ghtester
Copy link
Copy Markdown

ghtester commented Jan 20, 2022

OK, so the very first quick test - 74hcSetAllHigh command worked OK but after reboot the all outputs are set to low...
Currently I am using D3 as Data, D7 as CLK and D8 as Latch.
Bit operation works for outputs 1,2,..
But for output 0 I get:
Command unknown: 74hcSet,0,1

@tonhuisman
Copy link
Copy Markdown
Contributor Author

Ah, the check looks for 1..8, but I didn't subtract 1 from the pin number provided before setting that pin. Will fix.

Would you expect to set pins 0..7 or 1..8 ? (and 8..15 or 9..16 for the second chip, etc.?)

@ghtester
Copy link
Copy Markdown

ghtester commented Jan 20, 2022

It does not matter for me, I don't know what's better - perhaps starting from 1 would be better.

The major issue for me - it's the reset outputs to low during reboot. I need to analyze if that's due to used GPIOs or what's the reason.

@tonhuisman
Copy link
Copy Markdown
Contributor Author

after reboot the all outputs are set to low...
Currently I am using D3 as Data, D7 as CLK and D8 as Latch.

Looking at the page I shared earlier, I'd try to avoid D8 and D3, as they are not OK in that list, they may output some signal at boot.
If the Latch wouldn't be triggered at boot it should be fine, so connecting that to an OK gpio like 13(D7), that will probably help.

@ghtester
Copy link
Copy Markdown

Thanks for the comment, I'll give it a try. I am already using OK pins for another purpose so that's why I am trying those with exclamation mark first. :-) I understand I'll probably have to change that.

@ghtester
Copy link
Copy Markdown

ghtester commented Jan 20, 2022

Just tried to swap D7 and D8 so the Latch pin is connected to 'safe' D7, Clock to D8 and Data to D3.
The outputs are still set to 0 during node reboot.

So then I tried to reconnect the Clock pin to 'safe' D6 instead of 'unsafe' D8 (so only Data pin is connected to 'unsafe' D3) but the output clear still happens after reboot.
Are you sure there's no shiftregister initialization (zeroing) at boot?

BTW. How can the Hex State_A-3_0, State_A - State_D be used? I thought the State_A was updated in accordance to bits set through the 74hcSet (when I have just one shiftregister) but the all Values are always 0 (until set manually by Taskvalueset).
image

@tonhuisman
Copy link
Copy Markdown
Contributor Author

The outputs are still set to 0 during node reboot.

I spoke too soon, earlier, the registers where actually reset to off, at startup, sorry 😊, but that should now be fixed. The internal buffer is reset, but the state is now not sent out to the registers until a command to change them is used.

The State_A..State_D variables are used to represent the Hex or Bin pin states for up to 16 chips, that's what the 'Offset for display' setting is for. Not sure if I should suppress the regular variables, they won't handle the higher values (use TaskRun,relays to get the current state into those variables, it will sometimes display just 0 or nan, 'not a number', even though there is a sensible value in there, that has to do with storing a 32 bit unsigned int value in a float).

@ghtester
Copy link
Copy Markdown

ghtester commented Jan 20, 2022

Great, thank you for updates! I am going to recompile my custom build again, upgrade the node firmware and test again.
It would be nice if the buffer could be reset only at cold boot (don't know if it's ever possible to achieve). The best would be to fill the internal buffer value from plugin Values (State_A...State_D, which are stored in RTC memory so preserved during warm boot).

Stupid me, but I still don't understand how to operate with the State_A...State_D values. Currently there's no relation with pin states, the values are all zero despite bits are set and TaskRun, Relays command is performed.
image

@tonhuisman
Copy link
Copy Markdown
Contributor Author

the values are all zero despite bits are set and TaskRun, Relays command is performed.

The current state should be reflected in the Hex State_A ... just above the State_A value. Maybe I have the bytes in the wrong order, I'll check.

The best would be to fill the internal buffer value from plugin Values (State_A...State_D, which are stored in RAM so preserved during warm boot).

I'll investigate how to restore the values after a warm reboot.

@ghtester
Copy link
Copy Markdown

ghtester commented Jan 20, 2022

FYI I have changed the Number of chips to 4, then 74hcSetAllHigh and TaskRun,Relays and this is the result:
image
It looks when Number of chips = 4 it works... :-)
74hcSet,1,1 74hcSet,2,1 TaskRun,Relays:
image

@tonhuisman
Copy link
Copy Markdown
Contributor Author

tonhuisman commented Jan 20, 2022

After issuing the commands 74hcset,1,1 and 74hcset,8,1 and taskrun,relays, (and I set the display to Bin), I have this result:

image

The State_A variable is unexpectedly not displaying the current value, so I'll have a look into that.

You are showing the nan value I wrote about earlier, that is also something to investigate, it could know the value is set as an unsigned 32 bit integer (I set it using the designated support function), so it could display like that. I tried to set decimals to 2 and even 5, but then it still shows 0.00(000) 😞

Edit: Number of chips is still set to 1.
Edit2: You can set the Interval > 0 on the task to automatically update the Hex/Bin State display.

@ghtester
Copy link
Copy Markdown

You can set the Interval > 0 on the task to automatically update the Hex/Bin State display.

FYI when I set the Interval >0, the periodical crashes encountered:

Boot: Exception (18)
Reset Reason: Exception
Last Action before Reboot: PLUGIN_READ: timer, id: 9
SW WD count: 0

@ghtester
Copy link
Copy Markdown

Is it necessary to make a change in my Custom.h after recent changes in source codes? I can't compile with Vagrant anymore:

default: Indexing .pio/build/custom_IR_ESP8266_4M1M/libFrameworkArduino.a
default: Linking .pio/build/custom_IR_ESP8266_4M1M/ESP_Easy_mega_20220212_custom_IR_ESP8266_4M1M.elf
default: /home/vagrant/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: .pio/build/custom_IR_ESP8266_4M1M/src/src/Helpers_tmp/__tmpfile.cpp.o:(.text._Z10PluginInitv+0xa4): undefined reference to `Plugin_126(unsigned char, EventStruct*, String&)'
default: collect2: error: ld returned 1 exit status
default: *** [.pio/build/custom_IR_ESP8266_4M1M/ESP_Easy_mega_20220212_custom_IR_ESP8266_4M1M.elf] Error 1

@tonhuisman
Copy link
Copy Markdown
Contributor Author

The inclusion of the separate Plugin_nnn functions has moved to Plugin_init.h/.cpp, so no longer auto-managed by the ino to cpp conversion. So if you have a plugin enabled of which the source is not available you will see this compiler error. Once you disable the #define USES_P126 in your Custom.h you should be fine again.

@ghtester
Copy link
Copy Markdown

Thanks for the feedback. The question is if I am still able to compile with PR#3917 when I disable P126 in Custom.h ?

@tonhuisman
Copy link
Copy Markdown
Contributor Author

The question is if I am still able to compile with PR#3917 when I disable P126 in Custom.h ?

Well, I expect you got this error when compiling another branch of ESPEasy, that doesn't have this plugin available.
When compiling this PR you can should enable the #define, to have it included, of course 👍

@ghtester
Copy link
Copy Markdown

Yeah I am always compiling the main branch in first step as there's a script that (re)builds the Vagrant environment completely from scratch. In second step (to compile with a PR not yet merged) I am conencting to already running Vagrant virtual machine and starting a compilation there (with PR parameter).
So I did the same now, ignored the 1st step compilation error and the second step finished succesfully. Thanks for your advice.

@tonhuisman
Copy link
Copy Markdown
Contributor Author

@ghtester I have changed the commands for this plugin to now be 'prefixed' with 74hc595 instead of just 74hc as I've added a PR for 74HC165, where I used 74hc165 as command prefix, to better distinguish these commands.

@uzi18
Copy link
Copy Markdown
Contributor

uzi18 commented Feb 24, 2022

@tonhuisman maybe shiftin and shiftout instead of 74hc...

@tonhuisman
Copy link
Copy Markdown
Contributor Author

@tonhuisman maybe shiftin and shiftout instead of 74hc...

Very good suggestion, I will change both plugins, P126 to shiftout,<subcommand>,<args>... and P129 to shiftin,<subcommand>,<args>...

@ghtester
Copy link
Copy Markdown

Well, just another idea (when there's another change pending yet) - there are existing commands GPIO and PCFGPIO, maybe it would be nice to keep GPIO in the new commands (related to shift I/O pins) as well. What do you think?

@tonhuisman
Copy link
Copy Markdown
Contributor Author

there are existing commands GPIO and PCFGPIO, maybe it would be nice to keep GPIO in the new commands (related to shift I/O pins) as well.

Well, there are a few reasons I'm less fond of that idea. GPIO stands for General Purpose Input Output, and that's not what these are, they are either output or input, so IMHO that wouldn't actually match the 'Input Output' part. And having commands like shiftgpioout, shiftgpioin or shiftgpo and shiftgpi are quite hard to read, where shiftin and shiftout are much better comprehendible, short and to the point, having short command names is also a plus in my book.

@uzi18
Copy link
Copy Markdown
Contributor

uzi18 commented Feb 25, 2022

@tonhuisman Asked for change cmd name because there are available also others shift registers than 595 and 165 you can use here. Maybe should mention that earlier but it still waiting to merge.

@tonhuisman
Copy link
Copy Markdown
Contributor Author

there are available also others shift registers than 595 and 165 you can use

Yes, that is the main reason I agree with your proposed command rename 😃, and the second reason the commands being better readable.
I mention a few other chips in the documentation for this plugin. Have to investigate and include that for P129 as well.

@ghtester
Copy link
Copy Markdown

OK, I understand, you are right. I also prefer a short command names. Hopefully the command name changes will be final. ;-)

@tonhuisman
Copy link
Copy Markdown
Contributor Author

Hopefully the command name changes will be final. ;-)

It is nicely in line with many other plugins command handling now, shouldn't need to change again.

The only change I'm now thinking of is the name of the plugin, currently it's Output - 74HC595 Shiftregisters, but maybe here also the chip name should be removed.
The only issue I have with that is the name is then quite unspecific, Output - Shift registers (adding a space as well, to use correct English). Then P129 should also be renamed to Input - Shift registers, making these plugins more difficult to distinguish.
Probably, less is more, in this case 🤔

@TD-er TD-er merged commit 863a0cd into letscontrolit:mega Mar 31, 2022
@tonhuisman tonhuisman deleted the feature/p126-74hc595-shiftregisters branch March 31, 2022 11:03
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.

4 participants