|
Post by papa on Jun 14, 2017 20:36:48 GMT
How to Add a Node Feature (Photoresistor)
Updated March 23, 2019 for at least openHAB 2.5.0.M1, MQTT 2.x Binding, & the Embedded MQTT Broker
Needed in order for the following to work: See this thread on achieving an RFM69 Gateway & RFM69 nodes. See this thread on installing openHAB/MQTT on a local network-connected computer.
With his wireless gateway & DHT node sketches, computourist provides a great foundation on which to build more node possibilities. I adapted the node sketch to a Multi-Choice Node sketch (contains "choices" in the name) so one could choose node features & I added more features to it. I would like to see others add more features to the node sketch. I believe I can encourage that by describing how I add node features to the sketch. For an example, I will add a feature using a photoresistor which is also known as a photocell or a Light Dependent Resistor (LDR). Perhaps by watching my process, you will be inspired to develop & post here another new node feature.
This thread presupposes some experience with Arduino programming & in building these RFM69 wireless devices. If you do not have such experience, I recommend you start with this most basic, step by step thread & come back to this thread. The Photoresistor Node will need the gateway whose build is described in that step by step thread. Next, First Steps in Adding a Node Feature
|
|
|
Post by papa on Jun 14, 2017 21:24:25 GMT
First step in adding a node feature: Choose what you'll add (photoresistor). Next, find resources to help. On the Internet or in your printed resources, look for 1) a schematic (or breadboard mock up) & 2) an Arduino sketch using that schematic. I searched for Arduino measure light intensity with photoresistorNext, prepare to adapt a relevant schematic you find: (Unless you'll use a regular Arduino Uno with a RFM69 Breakout Board) convert 5 volt connections to 3.3 volts. Do not use Arduino pins needed by the RFM69 radio (D2, D10-D13) or other node features you intend to use (like D9 which can activate a relay). (<< Click on pic for larger view) ^^ I found this breadboard mock up for connecting a photoresistor (LDR) to an Arduino. (Note the 5 volt connection to be changed. the mock up used a 100 kilo ohm resistor which I changed to 47 kilo ohms. I've also seen 10 kilo ohms used as in the comments of the Test_Photocell.ino sketch offered below. See what resistance works best for you.) Here's a ^^ resulting first wiring diagram for a node with a photoresistor. (changed to 3.3 volt connection, option of 47 kilo ohm resistor or 100 kilo ohms.) Next, from the above schematic, make a prototype with Arduino compatible, solderless breadboard, & other necessary parts. For now, you can just make the photoresistor (photocell, LDR) connections to the Arduino (left side of the schematic) & add the RFM69 radio connections later.
|
|
|
Post by papa on Jun 14, 2017 21:52:05 GMT
Next get / adapt a working, non-node sketch with Serial Monitor output that will use the Arduino / photoresistor mock up / schematic. Test_Photocell.ino (1.25 KB) ^^ Here's such a test sketch, Test_Photocell.ino. It includes code (which I disabled) that will adjust an LED's brightness inversely to the light read by the photoresistor. Upload the sketch to the Arduino / photoresistor mock up. Open the Arduino IDE Serial Monitor (SM). The SM output numbers (integers, whole numbers, no decimal) should go up with increased light on the photoresistor & go down with increased darkness. For the purposes of later adapting this code to a node, notice this sketch has three sections: 1) Initial comments & variables 2) void setup() or "run once" code 3) void loop() or a sketch's main loop that will cycle continuously once entered. In adapting the code to a node, we will likely move relevant contents of these three sections into the same sections of the node sketch. Test_Photocell.ino's section 1) relevant to a node sketch's initial comments & variables: int photocellPin = 0; // [this integer variable] says the [photo]cell and pulldown resistor are connected to [Arduino pin] A0 int photocellReading; // [integer variable] to hold the analog reading from the sensor divider Test_Photocell.ino's section 2) relevant to a node sketch's setup() section: As indicated below, none of this section is needed for the node sketch. Test_Photocell.ino's section 3) relevant to a node sketch's main loop: photocellReading = analogRead(photocellPin); Serial.print("Analog reading = "); Serial.println(photocellReading); // [output on the Serial Monitor:] the raw analog reading
|
|
|
Post by papa on Jun 15, 2017 0:13:57 GMT
Next, prepare to use the relevant Test_Photocell.ino code in the Multi-Choice node sketch (...choices_pub.ino): From using the test sketch with the test Arduino circuit, notice the type of data that the new feature needs: Is the data input (to the Arduino sketch) or output (by the Arduino sketch) or both? Will the data be binary (0 or 1, OFF or ON) or integer (whole numbers, no decimal) or "real" (floating point, may have decimal point) or string (text)? This will indicate what node device to use. The test sketch Test_Photocell.ino shows that Arduino will input integers from the photoresistor circuit.
The following table of possible devices derives from computourist's gateway sketch: - Binary output (0/1 OFF/ON like LED, relay) uses devices 16-31. - Integer output whole numbers (like pwm, dimmer) uses devices 32-39. - Binary input (0/1 OFF/ON Open/Closed like button, switch, PIR-sensor) uses devices 40-47. - Real input (may have a decimal point like temperature, humidity) uses devices 48-63. - Integer input (whole numbers like light intensity) uses devices 64-71. - Transparent string transport (text output like to an LCD) uses device 72.
Again from the above, find the type of input or output & the range of devices used for it. If possible find an unused device in that range. If not possible, pick a device ID you can reuse that will not interfere with other features you desire on this node. If possible, learn from other devices in that range that the multi-choice sketch uses.
Since the Arduino will input integers for this new node feature, the sketch will use a device ID in a range from 64 through 71. Up to this point, in the latest multi-choice node sketch, devices 64 & 69-71 are not used. For this new node feature (photoresistor), we will use device 64.
|
|
|
Post by papa on Jun 15, 2017 18:27:10 GMT
Adapting SOILMOIST code (mostly) to create PHOTORESISTOR code Updated, March 25, 2019
From here, forum members (free registration) can download the latest choose_nodes sketch & follow the basic customization in that thread. The sketch already includes the PHOTORESISTOR coding that I will describe below. (Note: this sketch can be customized for several types of nodes with separate or combined features. See the linked list here.) In the latest Multi-Choice Node sketch, added PHOTORESISTOR coding will be indicated below by this bright blue text. The SOILMOIST feature ( device 67), using a soil moisture sensor, is in the same class of devices, integer input, as we need for PHOTORESISTOR (device 64). For the most part, as follows, I have adapted the PHOTORESISTOR code from that for SOILMOIST. See this summary comment for device 67, // 67 soil moisture, int. data: A0. Power flips between D6 & D7. changed from orig D7 & D8. A little earlier, I adapted the device 67 comment to add a summary comment for new device 64. // 64 light intensity via photoresistor, int. data: A0. Continues below
|
|
|
Post by papa on Jun 15, 2017 18:36:08 GMT
Adapting SOILMOIST code (mostly) to create PHOTORESISTOR code (continued):
Previously, the last version history comment read: // version 2.2MgE, Papa: added leak detector
I added this comment line:, // version 2.2MgF, Papa: added light intensity via photo resistor
Previously, the VERSION variable read: #define VERSION "2.2MgE" // version of this sketch, can be queried as device 3
With some logic, I changed the VERSION variable to: #define VERSION "2.2MgF" // version of this sketch, can be queried as device 3 It might have been changed to: #define VERSION "2.2MgE2" // version of this sketch, can be queried as device 3
Within the list of node feature choices (after line 20), create (in ALL CAPS) a name to define the new feature. Put it in the list as a non-compiling comment (starts with //): // #define PHOTORESIST
When you want to use this feature, delete the comment sign (//) & change the line to: #define PHOTORESIST
Continues below
|
|
|
Post by papa on Jun 15, 2017 18:39:56 GMT
Adapting SOILMOIST code (mostly) to create PHOTORESISTOR code (continued):
From here on, we will appropriately place conditional compilation for PHOTORESISTOR later in the sketch. It could look like #ifdef PHOTORESIST [code compiled if PHOTORESIST is defined near the sketch's beginning] #endif // end of ifdef PHOTORESIST
Or it could look like #ifndef PHOTORESIST [code compiled if PHOTORESIST is NOT defined] #endif // end of ifndef PHOTORESIST
Get clues about placement & coding from other features in that range & type of devices. In the multi-choice node sketch, if you look at the integer input features that use devices 65-69 (SUMP, WATERLEVEL, SOILMOIST, GDOOR, & LEAK), you may see that SOILMOIST node (device 67) sends a range of integer numbers to the Arduino. So then in the choices sketch, you can search (CTRL F) for code that has SOILMOIST or case (67), & then be able to model PHOTORESIST / device 64 after that.
Sometimes you can use an existing device as is or add or subtract from it by using #ifdef or #ifndef. Note 1): In the multi-choice node sketch, I used #ifdef & #ifndef to adapt WATERLEVEL (device 66) to LEAK (device 69). Note 2): two different nodes can use the same device ID with different features, but one node CANNOT use the same device ID for different features.
Continues below
|
|
|
Post by papa on Jun 15, 2017 18:52:30 GMT
Adapting SOILMOIST code (mostly) to create PHOTORESISTOR code (continued):
Early after the configuration lines (list of feature choices & other customization like NODEID), place code from the original sketch (Test_Photocell.ino) that comes before the void setup() section.
See these lines before the void setup() section, #ifdef SOILMOIST #define voltageFlipPin1 6 // changed from original 7 #define voltageFlipPin2 7 // changed from original 8 #define SoilMstPin 0 // A0 analog input int flipTimer = 1000; float TempFactor = 1; // Multiplying factor to adjust soil moisture by temp, intialize at no change #endif // ifdef SOILMOIST
^^ To adapt these SOILMOIST lines for PHOTORESISTOR code, replace SOILMOIST variables with variables from Test_Photocell.ino before the void setup() section. Bracket the lines with conditional compiling code. This produces: #ifdef PHOTORESIST int photocellPin = 0; // the cell & 10K pulldown connect to A0 int photocellReading; // analog reading from the sensor divider #endif // end of ifdef PHOTORESIST
^^ This code only compiles if #define PHOTORESIST is UNcommented (no // before #define)
Next, find the lines that begin with bool send, the message triggers for each device. Add send64 & make sure a single comma goes before it (unless it directly follows bool) & after it (unless it is the last listed item & is followed by a semicolon).
Continues below
|
|
|
Post by papa on Jun 15, 2017 19:03:16 GMT
Adapting SOILMOIST code (mostly) to create PHOTORESISTOR code (continued):
After void setup() & before setup's ending curly bracket ( } ), place code from the original test sketch's setup() section.
Multi-choice Node sketch already has the option of Serial Monitor debugging output. So we don't need to transfer anything here from the original test sketch.
The void setup() section is for "run once" code. When working on other features, find the Multi-Choice Node sketch's void setup() section to see what coding needs to be there.
Continues below
|
|
|
Post by papa on Jun 16, 2017 0:38:54 GMT
Adapting SOILMOIST code (mostly) to create PHOTORESISTOR code (continued):
In the void loop() & other sections, appropriately place code from the original test sketch in that section, but more so imitate coding from other features.
About line 643, each defined feature has Serial Monitor debugging output which declares that feature is operating.
See the lines, #ifdef SOILMOIST Serial.print(" SoilMst"); #endif // ifdef SOILMOIST Adapt NEW lines to #ifdef PHOTORESIST Serial.print(" LDR"); // LDR = Photoresistor #endif // ifdef PHOTORESIST
See the lines, #ifdef SOILMOIST case (67): // soil moisture value if (mes.cmd == 1) send67 = true; break; #endif // ifdef SOILMOIST
Adapt NEW lines (earlier by numerical order) to #ifdef PHOTORESIST case (64): // light intensity value if (mes.cmd == 1) send64 = true; break; #endif // ifdef PHOTORESIST
Continues Below
|
|
|
Post by papa on Jun 16, 2017 0:46:07 GMT
Adapting SOILMOIST code (mostly) to create PHOTORESISTOR code (continued):
Continuing in the void loop() section & still searching for ifdef SOILMOIST ...
See these lines, BUT PROBABLY DO NOT IMITATE THEM. #ifdef SOILMOIST #ifdef ACTOR if (retx) digitalWrite(ACT1, 0); // Turn off irrigation ACTOR if node loses connection with Gateway #endif // ifdef ACTOR #endif // ifdef SOILMOIST
Also see these lines, BUT DO NOT IMITATE THEM. #ifdef SOILMOIST ... if (send67) { // ... mes.devID = 67; ...
Instead see & adapt these lines, #ifdef SUMP if (send65) { mes.devID = 65; mes.intVal = LevelStat; // Sump level status code 0-2 (int) send65 = false; txRadio(); } // end of if (send65) #endif // ifdef SUMP
Adapt NEW lines to include void loop() coding from the test sketch (This code reads the photoresistor value & assigns it to an integer variable that will be sent to the gateway.) #ifdef PHOTORESIST if (send64) { mes.devID = 64; photocellReading = analogRead(photocellPin); #ifdef DEBUG Serial.print(" Analog reading = "); Serial.println(photocellReading); // raw analog reading #endif // ifdef DEBUG mes.intVal = photocellReading; // light intensity data to send send64 = false; txRadio(); } // end of if (send64) #endif // ifdef PHOTORESIST
Continues Below
|
|
|
Post by papa on Jun 16, 2017 0:54:46 GMT
Adapting SOILMOIST code (mostly) to create PHOTORESISTOR code (continued): Continuing in the void loop() section & still searching for ifdef SOILMOIST ... See the lines, #ifdef SOILMOIST send67 = true; // send soil moisture value #endif // ifdef PHOTORESIST Adapt NEW lines (a little earlier in numerical order) to #ifdef PHOTORESIST send64 = true; // send light intensity value #endif // ifdef PHOTORESIST ================================== Now find void parseCmd() & in the following list, add the line send64 - false; // light intensityFrom here, download the latest choose_nodes sketch & do the basic customization. The sketch includes photoresistor code. As usual in the sketch, you need to customize NODEID (I'll use NODEID 18 20 for the following), ENCRYPTKEY, DEBUG, FREQUENCY, & IS_RFM69HW. Perhaps using a solderless breadboard, construct the full node (with RFM69 radio) according to the schematic above. Be sure that #define PHOTORESIST is UNcommented (no // to start it) & that the NODEID is 18 20. << changed March 23, 2019Upload the sketch, troubleshoot any errors, turn on / observe the Serial Monitor Output. Every 60 seconds, on separate lines for Node 18 20 you should see reports of devices 2, 4, 9, & 64. Device 64 is reported on 2 lines, one of them starting with "Photoresistor Analog reading =" Again, the node's device 64's Ival (integer value) should go up with increased light on the photoresistor & go down with increased darkness Continues Below with OpenHAB configurations
|
|
|
Post by papa on Jun 16, 2017 15:28:29 GMT
Once the node is sending photoresistor data, we can use it in OpenHAB. You might read this thread on interpreting OpenHAB config file entries. OpenHAB Configurations Related to a Photoresistor Node:
PaperUI\configuration\Things Add Thing (click + in blue disc) click MQTT Binding Add Manually Generic MQTT Thing Node20 Location (arbitrary physical location) Shop MQTT Broker - mqtt:systemBroker:embedded-mqtt-broker save (click check mark in blue disc)
PaperUI\Configuration\Things\Node20 Add channels (click + in blue disc)
Type: Text Channel ID: Node20Channel02 Label: Node20_RSSI State topic home/rfm_gw/nb/node20/dev02
Type: Number Channel ID: Node20Channel04 Label: Node20_Volts State topic home/rfm_gw/nb/node20/dev04
Type: Number Channel ID: Node20Channel64 Label: Node20_Photoresistor State topic home/rfm_gw/nb/node20/dev64
.items file addition (Node20.items in openHAB's \conf\items folder): In this post, see this item using the soil moisture data: Number SoilMst_80 "Soil Moisture Level_80 [%s]" <humidity> {mqtt="<[mosquitto:home/rfm_gw/nb/node80/dev67:state:default]"} Adapt this ^^ for the Photoresistor data: It's using node 80 (change to 18 20) & device 67 (change to 64). << NODEID changed March 23, 2019 For a suitable icon, look in your OpenHAB images folder: For Windows, go to C:\openhab\webapps\images For Linux (incl. Raspberry Pi), go to /usr/share/openhab/webapps/images/ Or you can look online, including jimkernsjr's extensive icon collection (both .png & .svg types) I changed the humidity icon to sun.png in my OpenHAB images folder. The adapted item for Node20Photoresist.items in openHAB's \conf\items folder: Number Light_20 "Light Level_20 [%s]" <sun> { channel="mqtt:embedded-mqtt-broker:topic:mything:Node20Channel64" }
Other items: String Node20RSSI "Node20rssi (db)[%s]" <network> (Nodes) { channel="mqtt:embedded-mqtt-broker:topic:mything:Node20Channel02" } Number Node20Vlts "Node20Volts [%.2f Vdd]" <battery> (Nodes) { channel="mqtt:embedded-mqtt-broker:topic:mything:Node20Channel04" }
Important: Link the above created items to the further above matching channels.
.sitemap file (\conf\sitemaps folder) entry to display light intensity Text item=Light_20 With the above, on OpenHAB's User Interface, you could watch the light intensity in a garden area or a room that gets sunlight. The node sends data every 60 seconds so display changes can delay by that much. OpenHAB Configurations Related to a Photoresistor Node, Continue Below
|
|
|
Post by papa on Jun 16, 2017 15:35:53 GMT
Using the Photoresistor Node's Data in OpenHAB, Continued Updated on March 23, 2019
What if we wanted to make more use of the photoresistor data? What if we wanted to monitor the state of a light in a place not often visited (like the light over a workshop area)? Add to \conf\items\ Node20Photoresist.itemsString Shp_Light "Shop Brightness [%s]" <light> Add to .sitemap fileText item=Shp_Light OpenHAB Configurations Related to a Photoresistor Node, Continue Below
|
|
|
Post by papa on Jun 16, 2017 15:43:16 GMT
Using the Photoresistor Node's Data in OpenHAB, Continued Updated March 23, 2019
Data for the dimmest lighting over my photoresistor was 634 so I used 700 in the rule below. ( Instead of 700, use a value somewhat above your dimmest reading.) As follows, in openHAB's \conf\rules folder, create Node20Photoresist.rules
rule "Shop_Lighting_State" when Item Light_20 received update // update of photoresistor value then if(Light_20.state < 700) // ?? below level rated as dim ?? { Shp_Light.postUpdate("OFF") // on UI set dim light icon & display OFF } else { Shp_Light.postUpdate("ON") // on UI set bright light icon & display ON } end If Node 20's photoresistor value (sent to openHAB every 60 seconds) is less than 700, Shop Light's icon on the User Interface will be dim. At greater than 700, the icon will be bright. Also the User Interface will display ON & OFF at the right as well as change the icon on the left. Adding to the Usefulness of a Photoresistor Node, Continues Below
|
|
|
Post by papa on Jun 17, 2017 16:12:05 GMT
Adding to the Usefulness of a Photoresistor Node, ContinuedWith added circuitry & programming, we can increase the photoresistor node's usefulness. << Click on pic for larger view. ^^ Near the middle of this schematic, see added circuitry for a solid state relay (SSR). The SSR can turn a light or other AC appliance on & off. See here about using SSRs.
|
|
|
Post by papa on Jun 17, 2017 16:17:14 GMT
Taking Advantage of the Solid State Relay (SSR) Added Above: On March 23, 2019, 18 was changed to 20
In the choose_nodes sketch, also UNCOMMENT // #define ACTOR. Upload the changed sketch to the node.
Go to PaperUI\Configuration\ Things\Node20 To Add a Channel, Click on the "+" in a blue disc beside "Channels" In the Add Channel Window, fill the fields: Channel type On/Off switch < choose type according to the item data type we want Channel id Node20Channel16 < arbitrary ? as long as we match in a linked item later Label Node20_Switch < arbitrary ? MQTT State Topic home/rfm_gw/nb/node20/dev16 Command Topic home/rfm_gw/sb/node20/dev16 .items fileSwitch Act_Node20 { channel="mqtt:embedded-mqtt-broker:topic:mything:Node20Channel16" } .sitemap fileSwitch item=Act_Node20 With the added SSR circuit & the above added OpenHAB config file entries, the OpenHAB User Interface will have a virtual switch to control the AC appliance on the SSR. We can also use the photoresistor data to switch the appliance via the SSR. See the next post.
|
|
|
Post by papa on Jun 17, 2017 16:18:53 GMT
With the added SSR circuit & the above added OpenHAB config file entries, the OpenHAB User Interface will have a virtual switch to control the AC appliance on the SSR. We can also use the photoresistor data to switch the appliance via the SSR.
Add the following to the OpenHAB configuration files ... ( On March 23, 2019, 18 was changed to 20)
In openHAB's \conf\rules folder, edit Node20Photoresist.rules adding two new lines:
rule "Shop_Lighting_State" when Item Light_20 received update // update of photoresistor value then if(Light_20.state < 700) // ?? below level rated as dim ?? { Shp_Light.postUpdate("OFF") // on UI set dim light icon & display OFF sendCommand(Act_Node20, ON) // need light, turn appliance on } else { Shp_Light.postUpdate("ON") // on UI set bright light icon & display ON sendCommand(Act_Node20, OFF) // have enough light, turn off appliance } end The above, for example, ensures enough available or appliance light. This could provide light for safety's sake. Or one could control a grow light to supplement a plant's sunlight.
|
|
|
Post by papa on Mar 30, 2019 14:03:48 GMT
Forum readers, I updated the above thread to be compatible with openHAB 2.5.0.M1, MQTT 2.x Binding, & the Embedded MQTT Broker.
The above thread describes & gives an example of how I add a new node feature.
I hope it will be helpful & useful for you,
What new node feature will you implement? Please share your creations on this forum.
|
|