Review of a nice 8 ...
 
Notifications
Clear all

Review of a nice 8 channel i2c solid state relay board available  

Page 1 / 2
  RSS

tico
 tico
(@tico)
Trusted Member
Joined: 3 months ago
Posts: 65
July 22, 2020 2:35 pm  

Hi all, I found a really nice 8 channel solid state relay board on amazon with an i2c interface built into it, and I've got it working with Mycodo pretty well using my ugly bash shell script, so I thought I'd let anyone else know about this option, (and share the code i've written).

I don't believe the company has a website of their own besides a facebook page ( https://www.facebook.com /krida.electronics/) and a support email, however it's available on Amazon (and a few other places) for $40:

https://smile.amazon.com/gp/product/B07JGSNWFF/ref=ppx_yo_dt_b_asin_title_o07_s00?ie=UTF8&psc=1

The SSRs on it are good for 2A, and the chip controlling it has had no problems with 3.3V i2c signalling. As the Amazon description says, it supports 8 different i2c addresses from 0x27 and upwards. It's produced in Latvia, and after a quick email with the producer he clarified that there's two versions of the board -- V1 (which is what I bought at the amazon link above) uses logical 1 to enable the relay, and 0 to disable it, however the circuit configuration is such that when the board is powered on all relays are enabled by default until subsequent commands to disable them are sent. The V2 version of the board is the opposite ("1" disables a relay, 0 enables it, and all relays are powered off by default).

Quote:
Плата V1 - при первом включении все реле включены. Управление - логической "1" включается реле, логическим "0" отключается реле. Снята с производства!
Плата V2 - при первом включении все реле отключены. Управление - логическим "0" включается реле, логической "1" отключается реле. 

Also, the chip used is a write-only chip -- it's not possible to read the current status of a relay with an i2cget command, so keeping track of which relays are enabled or disabled at any given time has to be done in the scripts for it. As a result I've kludged together a bash script that I've used successfully on my Pi 4B with Mycodo, and hopefully I've commented the script enough that others can modify it to suit their own needs.

https://github.com/ticomyco/Krida_8chan_i2c_relay_board_scripts

Hope this is helpful to someone!


Quote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 275
July 22, 2020 3:42 pm  

Nice work. Though, since Mycodo sets the state at startup, and stores the state, is the "init" really necessary when using with Mycodo?

Also, Mycodo now supports custom output modules that can be imported. So, you could write this in Python and it would be able to be integrated into an Output module for easy importing into Mycodo. Just another option than using the Linux Command Output.

Mycodo Developer


ReplyQuote
tico
 tico
(@tico)
Trusted Member
Joined: 3 months ago
Posts: 65
July 22, 2020 5:35 pm  

@kylegabriel Thanks! I wrote the scripts this way because I assumed that there would be the very likely possibility that I might have some other process using one or two relays on the same board, but having Mycodo controlling the remainder of the relays or something like that. I assume that it's a good idea to start from a known state (especially since the "init (on|off)" doubles as the "turn everything on or off" command as well as creating a statefile for subsequent calls of the script to modify. In my case I want to have the option to turn all relays off as soon as possible in a system boot, but perhaps that's too much premature optimization ...

That's cool about the output modules in Mycodo! Unfortunately the majority of my programming experience is with other languages (ASM, C, random ancient Unix/VMS/micro stuff that doesn't involve object oriented programming) before Python became popular, and aside from being pretty rusty on programming in general, I  haven't really played with Python much at all, beyond following instructions to install some random needed package, or reading thru some code to try to find hints as to why something might be crashing. I keep meaning to do some Python coding and get up to speed on it but life keeps happening. Anyhow, enough complaining -- I'll put this on my todo list as a hopefully very simple project to use to get up to speed with python. :)

Currently I'm not entirely sure how to test any sample python code within the environment that mycodo runs in with the specific bits installed via pip (as opposed to whatever python2.7, python3 etc environment that is available as a result of DEB packages installed thru the apt-get system). I need to spend some time really trying to dig into the codebase.

 

On a side note, in retrospect I realize that my previous post could have come off as a bit of an advertisement or something like that -- Is it appropriate/acceptable to post hardware reviews and such on this forum?

 


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 275
July 22, 2020 10:25 pm  
Posted by: @tico

Currently I'm not entirely sure how to test any sample python code within the environment that mycodo runs in with the specific bits installed via pip (as opposed to whatever python2.7, python3 etc environment that is available as a result of DEB packages installed thru the apt-get system). I need to spend some time really trying to dig into the codebase.

Here are a few tips that might help:

The Mycodo Python environment is located at ~/Mycodo/env with the python executable at ~/Mycodo/env/bin/python (Python 3.7) and pip executable at ~/Mycodo/env/bin/pip

The output modules are located at ~/Mycodo/mycodo/outputs and an example output module with a lot of comments is located at ~/Mycodo/mycodo/outputs/examples/example_dummy_output.py

The python virtualenv is set up to use any system-installed packages if they exist, but I discourage installing system python packages unless it's something that may take an hour to compile via pip (e.g. numpy), and in that case installing python3-numpy via apt is the better option (even though it will likely be a much older version). Otherwise, I install via "~/Mycodo/env/bin/pip install [python package]".

For communicating via I2C, you might want to refer to some of the Inputs (no output currently uses I2C). Specifically, the ones that have all the communication code within the Input module (and don't rely on an external library), such as the sht2x or mh-z16 inputs. The smbus2 module is what's typically used, and is fairly straightforward to use. After initializing it with the I2C address and bus number, you can then read or write.

If you wan to run small test scripts to try to initially communicate with the board before trying to implement the code into an output module, you can create a simple python script at ~/test_script.py:

from smbus2 import SMBus

i2c_bus = 1
i2c_address = 0x63

sensor = SMBus(i2c_bus)
sensor.write_byte(i2c_address, 0xF3)

Then, execute it in the Mycodo virtualenv with the command "~/Mycodo/env/bin/python ~/test_script.py"

 

Posted by: @tico

On a side note, in retrospect I realize that my previous post could have come off as a bit of an advertisement or something like that -- Is it appropriate/acceptable to post hardware reviews and such on this forum?

Sure, it's perfectly fine. If it was completely unrelated to Mycodo, I might take issue. But you not only introduced us to a nice piece of hardware, but wrote a script to control it!

Mycodo Developer


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 275
July 23, 2020 10:55 am  

It looks like there's already a PCF8574 python library available. It also appears the pin states can be read.

Mycodo Developer


ReplyQuote
tico
 tico
(@tico)
Trusted Member
Joined: 3 months ago
Posts: 65
July 23, 2020 11:56 am  

Oh man -- thanks for the very detailed reply! That's very helpful and I'm excited to dig into it when I get done with work!

I don't know if the PCF8574 can have a pin both set as an output (to control a relay) and also have its current status read. I took a quick look at the datasheet https://www.nxp.com/docs/en/data-sheet/PCF8574_PCF8574A.pdf and it appears that a pin has to be set as *either* an input or an output. I don't have the board in front of me currently so I can't tinker with it, but when I review my email with the creator

Quote:

"> Можно ли прочитать текущее состояние контактов включения реле с микросхемы pdc8574?

...

Текущее значение пинов с микросхемы прочитать нельзя. Нужно использовать переменную в коде программы, которая будет отвечать за состояние пинов."

he states that it is not possible to read the current state of an enabled relay, and that instead it is necessary for the microcontroller to use a variable to store the current status of the pins. I can try reading from it later on and see what happens.


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 275
July 23, 2020 12:07 pm  

Well, there's a get_pin_state function in the library, so we'll see if it works if you test it. I actually did some minor changes to the Mycodo framework to better accommodate I2C outputs. There aren't any I2C outputs currently supported, but I had built the framework to allow them with anticipation one would come around sooner or later. In my coding haste, I also created a yet-to-be-tested PCF8574 output module. I don't want to spoil the fun of writing/testing the Python code, so I'll push the edits with all the changes except the output module (since it's still untested). If you want me to post the module here for you to test, I will, but if you want to have a crack at it first on your own, I'll hold off. Your call ;)

Mycodo Developer


ReplyQuote
tico
 tico
(@tico)
Trusted Member
Joined: 3 months ago
Posts: 65
July 23, 2020 12:20 pm  
Posted by: @tico

.... it supports 8 different i2c addresses from 0x27 and upwards.

Correction -- it uses either addresses 0x20-0x27 (default 27) or 0x38-0x3F (default 3F) depending on which board version one has.


ReplyQuote
tico
 tico
(@tico)
Trusted Member
Joined: 3 months ago
Posts: 65
July 23, 2020 12:26 pm  

That's great about the framework! And thanks for the help :) I'll see what I can make happen when I get home and let you know


ReplyQuote
tico
 tico
(@tico)
Trusted Member
Joined: 3 months ago
Posts: 65
July 24, 2020 11:56 am  

Initial report -- it appears that (at least for the PCF8574 chip used in the V1 board) that indeed the pin state cannot be effectively read. If I have previously set all relays on (for example, with "i2cset -y 1 0x27 0xff") and I try to run "i2cget -y 1 0x27" with no other arguments I get a response of 0x00 and all relays are deactivated. If I then try to read the status of pin 1 with "i2cget  -y 1 0x27 0x01" then I still get a response of 0x00 however then pin 1 is activated. In fact after a number of tests, it's apparent that querying the board with i2cget and any byte value from 0 to 0xff always returns 0 and only 0, however it also enables/disables the relevant relays exactly the same as if I was passing the same value to an i2cset command.

 


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 275
July 24, 2020 12:45 pm  

What about with the pcf8574 python library?

Run "~/Mycodo/env/bin/pip install pcf8574", then execute the following code with "~/Mycodo/env/bin/python test_script.py":

from pcf8574 import PCF8574
i2c_port_num = 1 pcf_address = 0x20
pcf = PCF8574(i2c_port_num, pcf_address) pcf.port[0] = True
print(pcf
.port[0]) pcf.port[0] = False print(pcf.port[0])

Mycodo Developer


ReplyQuote
tico
 tico
(@tico)
Trusted Member
Joined: 3 months ago
Posts: 65
July 24, 2020 12:58 pm  

Also, it seems as though the pcf8574 library doesn't get the pin state on this board (just as i2cget fails to return anything other than 0 as well), and also it still requires the state of all pin states to be set each time one desires to change a single pin state.

---

from smbus2 import SMBus

i2c_bus = 1
i2c_address = 0x27

kridarelays = SMBus(i2c_bus)
kridarelays.write_byte(i2c_address, 0x0F)

--

The above turns on relays 1-4 and turns off relays 5-8 as expected. I looked at the examples on the README for the pcf8574 and tried them out, however I can't modify a single pin state without affecting others:

---

>>>from pcf8574 import PCF8574

>>>mypcf = PCF8574(1, 0x27)

>>> mypcf.port
[False, False, False, False, False, False, False, False] 

(incorrect, in fact relays 1-4  were already enabled)

>>> mypcf.port[0] = True

(Turns off all other relays but turns on relay 8)

>>> mypcf.port[7] = True

(as previous example, turns off all other relays but turns on relay 1)

>>> mypcf.port = [False, False, False, False, True, True, True, True]

turns on relays 1-4 and turns off relays 5-8. FYI, at any point regardless of relay state, mypcf.port continued to return only an array of False's.

 

EDIT:

Oops, just saw your response.

I believe I'm being redundant, but just to make sure:

>>> pcf = PCF8574(1, 0x27)
>>> pcf.port[0] = True
>>> print(pcf.port[0])
False
>>> pcf.port[0] = False
>>> print(pcf.port[0])
False

This post was modified 3 weeks ago 2 times by tico

ReplyQuote
tico
 tico
(@tico)
Trusted Member
Joined: 3 months ago
Posts: 65
July 24, 2020 11:45 pm  

@kylegabriel I'm looking at the example output module, and it seems like the output_state is only a boolean (and not a byte). It appears to me that the model is that an output is supposed to only control a single "thing" -- in this case of course a single relay channel -- at a time. Since it is not possible with this board to manipulate the state of a single relay channel without writing the byte (with the pre-existing states of the other channels) to the i2c bus, is there an  ideal place in Mycodo to store this data about the state of other channels?

I imagine creating output module for this board that would manipulate a single user-selectable channel, and the user would add 8 instances of this output module (in order to have unique device names for what each channel is controlling, etc) with each instance correlating to a different channel, but having them all update the same byte (wherever it's stored).

I've looked over the sht2x and mh-z16 input modules you mentioned, and a handful of other random ones, but I haven't seen anything that jumps out at me as doing anything similar to what I'm imagining is necessary -- is there somewhere else in Mycodo that I might find an example of what I'm trying to do? If not I'll see what I can figure out but I try not to reinvent the wheel whenever it's not necessary. :)

 

On another note, I went down a rabbit hole looking at translations, and since I've got my work computer defaulting to english I didn't see the other translations for the Mycodo interface, however after changing to spanish and russian I've noticed a good bit of missing (or awkward) translations, so if I manage to find a bunch of spare time hopefully I'll send you some updates :)


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 275
July 25, 2020 12:52 am  
Posted by: @tico

is there an  ideal place in Mycodo to store this data about the state of other channels?

This is something that hasn't yet been needed, so there's no example I can give that currently exists in Mycodo. I'd suggest perhaps creating a file of the states that includes the I2C address/bus in the filename so each of the 8 channels will only write to the appropriate file if there are more than one board connected. I would also utilize lock_acquire() to gain a lock while writing this file. Something like this should work:

list_relay_states = [True, True, True, True, False, False, False, False]
write_file = "/var/lock/pcf8574_{}_{}
".format(self.i2c_bus, self.i2c_address)
lockfile = "/var/lock/lockfile_{}_{}".format(self.i2c_bus, self.i2c_address)

self
.lock_acquire(lockfile, timeout=10) if self.locked[lockfile]: try:
with open(write_file, 'w') as file:
file.write(",".join(['1' if x else '0' for x in list_relay_states]))
finally: self.lock_release(lockfile)

Mycodo Developer


ReplyQuote
Kyle Gabriel
(@kylegabriel)
Member Admin
Joined: 6 years ago
Posts: 275
July 25, 2020 12:56 am  
Posted by: @tico

after changing to spanish and russian I've noticed a good bit of missing (or awkward) translations, so if I manage to find a bunch of spare time hopefully I'll send you some updates :)

Yeah, you're likely to find some completely wrong translations in there. I used google translate to automatically translate the phrases, which is hit or miss when it comes to single word translations without context. However, hopefully it's better than nothing and allows some people to use Mycodo who normally wouldn't because of a language barrier. Thanks for the support.

Mycodo Developer


ReplyQuote
Page 1 / 2