Re: [mh] One Wire sensors
Rick Steeves <[email protected]>
| Newsgroups | gmane.comp.misc.misterhouse.user |
|---|---|
| Message-ID | <[email protected]> |
I've been using 1-wire sensors with MH for ... a really long time. There is indeed code for 1-wire in MH. Look under "ibutton". There's no need really to write a new module. I put something together that was a compilation of the MH iButton code, and then tweaked it. (see attached) I store the data in the Indoor temp rrd (see attached). Here's my build doc for the sensor housing as well: https://www.sinister.net/1wire/1wiretemp.htm Rick On 12/26/2020 9:02 AM, Stephen Switzer wrote: > Several years ago, I ordered a serial to RJ11 adapter from > ibutton(something), called the link 12, and a few temperature sensors > that look like the standard TO-92 transistor package. I connected it to > MH, added one sensor to the network and tried to see if it worked. I had > plans to place sensors all around the house. > > However, I hadn't ever seen any response from the serial port and > shelved the project. I decided to look at it again yesterday and > discovered how it worked... sort of: > > > f=First \=Snif > n=Next |=Thru > r=Reset l=Level > b=Byt(NN+) ^=57600 > j=Bit(N+) `=38400 > p=BytW/P ,=19200 > ~=BitW/P x=BusLo > d=Aux+ $=Scan > z=Aux- *=List > &=Aux? h=Help > (=Extend > t=Type "=Iso > > > 420008003BE45B10 > !,420008003BE45B10 > > I found that at 9600 baud I can press h to see the help, and *, $ will > also return data about the sensor that I have on the network. Wow! I > finally have something to work with, but I can't figure out where to get > the readings from. Pressing p, j or b all give a 1. One time I saw a B3, > but it doesn't seem to be repeatable. It's 179 anyway... my server room > rack better not be that temperature!! > > So, I continued and looked for some MH code to read the serial port > data. I found several examples, but none of them seemed to be for > reading the OW data directly from a serial port. All seemed to read a > dump from an external program - and all from Windows. I'm running Linux. > > So, I looked a owfs: installed it, configured it the best that I could > figure out and poked around the /run/owfs filesystem... > > root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/latesttemp > 43.1086root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/latesttemp > 91.3275root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/latesttemp > 14.4802root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/latesttemp > 94.4001root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/latesttemp > 46.0749root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/latesttemp > 90.8667root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/temperature > 36.8015root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/temperature > 1.73821root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/temperature > 31.6712root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/temperature > 65.0987root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/temperature > 27.7991root@avalanche:~# cat /run/owfs/bus.0/10.67C6697351FF/temperature > > Every time I checked values, it was something different. Perhaps this is > because I twisted the sensors onto the wires, instead of a more secure > connection? > > Either way, I'm getting SOMETHING... so I think it's time to ask: how do > YOU gather OW data? Is there a module for MH to tread it directly, or > should we use something external? > > Thank you all! > > -- > > Best regards, > Steve Switzer > > --- > Get world-class business I.T. services and a phone system with awesome features that won't challenge your budget! > http://www.sbsROC.com > > > > ________________________________________________________ > To unsubscribe from this list, go to: https://lists.sourceforge.net/lists/listinfo/misterhouse-users > -- Rick Steeves https://www.irelandbybicycle.com It's all fun and games until someone ends up wearing a cone. ________________________________________________________ To unsubscribe from this list, go to: https://lists.sourceforge.net/lists/listinfo/misterhouse-users
RickButton.txt
(text/plain, 16.7 KB)
# Category = iButtons #@ Manage iButton devices # Rick Steeves # [email protected] # My summary of 1-wire functionality mostly by functions for modularity # Running on Windows 2000/XP # There are a lot of iButton modules w/i mh that are bits and pieces # Almost 100% derived from the iButton modules within mh: # code\public\ibutton_ws_ernie.pl # code\common\iButton.pl # code\bruce\iButton_bruce.pl # and others but organized and working for my specific environment # To connect to the serial line, you need a serial to 1-wire adaptor # 1-Wire Serial Adaptor DS9097U-A from www.hobby-boards.com # Defined in mh.private.ini ##mh.ini: iButton_serial_port=COM4 (or whatever com port) #from iButton.pl. connect/disconnect to the iButton bus # I'm not using iButton.pl because it periodically also checks the bus, # and I don't want it to. So I copied out everything else. # Updated to send mail when the water detects water. 091231 $v_iButton_connect = new Voice_Cmd "[Connect,Disconnect] to the iButton bus"; $v_iButton_connect -> set_info('Use this to free up the serial port or test the iButton start/stop calls'); if ($state = said $v_iButton_connect) { print "$state the iButton bus\n"; if ($state eq 'Connect') { print_log &iButton::connect($config_parms{iButton_serial_port}); } else { print_log &iButton::disconnect; } } # List all iButton devices on the wire $v_iButton_list = new Voice_Cmd "List all the iButton buttons"; $v_iButton_list -> set_info('Lists the family and ID codes of all the buttons on the bus'); $v_iButton_list -> set_authority('anyone'); if (said $v_iButton_list) { print_log "List of ibuttons:\n" . &iButton::scan_report; # print_log "List of ibuttons on 2nd ibutton:\n" . &iButton::scan_report(undef, $config_parms{iButton_2_serial_port}) # if $config_parms{iButton_2_serial_port}; } # The 4 Channel Relay 4R3-R1-A from www.hobby-boards.com # http://www.hobby-boards.com/catalog/howto_4_channel_relay.php?referer=howto_mini_motion_detector.php # The first two characters are the device type. # In this case '05' is an addressable switch for the DS2405 my $ib_relay1 = new iButton '0500000032073e29'; my $ib_relay2 = new iButton '05000000320484af'; my $ib_relay3 = new iButton '0500000031fa0e06'; my $ib_relay4 = new iButton '0500000031f9ddd5'; # Can be defined instead in items.mht as example: # IBUTTON, 0500000032073e29, ib_relay1 $v_iButton_relay1 = new Voice_Cmd "Turn relay1 [on,off]"; $v_iButton_relay1 -> set_info('Controls Relay 1'); $v_iButton_relay1 -> set_authority('anyone'); $v_iButton_relay2 = new Voice_Cmd "Turn relay2 [on,off]"; $v_iButton_relay2 -> set_info('Controls Relay 2'); $v_iButton_relay2 -> set_authority('anyone'); $v_iButton_relay3 = new Voice_Cmd "Turn relay3 [on,off]"; $v_iButton_relay3 -> set_info('Controls Relay 3'); $v_iButton_relay3 -> set_authority('anyone'); $v_iButton_relay4 = new Voice_Cmd "Turn relay4 [on,off]"; $v_iButton_relay4 -> set_info('Controls Relay 4'); $v_iButton_relay4 -> set_authority('anyone'); if ($state = said $v_iButton_relay1) { print_log "Setting iButton relay1 to $state"; set $ib_relay1 $state; } if ($state = said $v_iButton_relay2) { print_log "Setting iButton relay2 to $state"; set $ib_relay2 $state; } if ($state = said $v_iButton_relay3) { print_log "Setting relay3 to $state"; set $ib_relay3 $state; } if ($state = said $v_iButton_relay4) { print_log "Setting relay4 to $state"; set $ib_relay4 $state; } # I have two sets of wireless transmitters for speakers in the house # hooked to the computer through a "y" splitter to the main computer speakers. # They're hooked to the relay switch. This way I can effectively turn off the # MH speakers throughout the house. Two relays, two channels (L&R). $v_iButton_Speakers = new Voice_Cmd "Turn Speakers [on,off]"; $v_iButton_Speakers -> set_info('Controls Relay 1 and 2'); $v_iButton_Speakers -> set_authority('anyone'); # I have wireless speakers connected to the first two relays (left and right channels) if ($state = said $v_iButton_Speakers) { print_log "Setting Speakers to $state"; set $ib_relay1 $state; set $ib_relay2 $state; #a general mh value defined in mh_sound set $mh_speakers $state; } # The iButton Temp/humidity Code my $object_name = ''; my $itemp = ''; # Temporary temp variable # I wanted to add temp, humidity, and water monitoring to my crawl space # 1-wire seemed like a good choice, but the devices I purchased were not as # simple to get working as I'd hoped, as I had to write Get_Vwet_2438 in Device.pm to do it! # For the DS2438 Chip, as used by the MS-TH and MS-THW at http://www.ibuttonlink.com # The DS2438 is type: 26 # As would be defined in items.mht #IBUTTON, 2600000081161fa8, ib_water #IBUTTON, 26000000809ad7f3, ib_temp1 #IBUTTON, 26000000815f600e, ib_temp2 #IBUTTON, 2600000080bb306a, ib_temp3 # The first 2 digits are the type, the last two the CRC, and the rest the ID # in this case the first (ib_water) is the temp/humidity/water sensor, the next two temp/humidity, and the last temp my $ib_sensor1= new iButton '2600000081161fa8'; # Sump 2438 Water $ib_sensor1->{object_name} = 'Water Sensor'; #my $ib_sensor2= new iButton '26000000809ad7f3'; # my $ib_sensor2= new iButton '100008013e7bdb5a'; $ib_sensor2->{object_name} = 'Computer Room'; # MH 1920 my $ib_sensor3= new iButton '26000000815f600e'; $ib_sensor3->{object_name} = 'Crawl Space'; # Crawl Space 2438 Humid my $ib_sensor4= new iButton '2600000080bb306a'; $ib_sensor4->{object_name} = 'Servers'; # Servers 2438 Temp only my $ib_sensor5= new iButton '100008013e9ebaa6'; $ib_sensor5->{object_name} = 'Den'; # Den 1920 my $ib_sensor6= new iButton '100008013e9a021f'; $ib_sensor6->{object_name} = 'Library'; # Library 1920 my $ib_sensor7= new iButton '100008013ebcdff5'; $ib_sensor7->{object_name} = 'Dining Room'; # Dining 1920 my $ib_sensor8= new iButton '100008013eaf1597'; $ib_sensor8->{object_name} = 'Bed Room'; # Bedroom 1920 # The order the sensors are read in - used to determine TempSpare order for RRD my @ib_sensors = ($ib_sensor1, $ib_sensor6, $ib_sensor3, $ib_sensor2, $ib_sensor5, $ib_sensor4,$ib_sensor7,$ib_sensor8); # the array of sensors # Sump Library Crawl computer Den Servers BedRoom Dining Room my @ib_sensorsRH = ($ib_sensor1, $ib_sensor3); my @ib_sensorsWet = ($ib_sensor1); my $ib; # temporary value as things are read of out the array # Read the temp from one 1-wire device $v_iButton_readtemp = new Voice_Cmd "Read temp [1,2,3,4,5,6,7,8]"; $v_iButton_readtemp -> set_info('Read the temperature from a specific button'); $v_iButton_readtemp -> set_authority('anyone'); if ($state = said $v_iButton_readtemp) { $ib = $ib_sensors[$state - 1]; $object_name = $ib->{object_name}; # Add to detect whether its family is a 2438 or a 1920 .. if ($ib->family eq '26') { $itemp = &Read_DS2438Temp($ib); print_log "DS2438: $object_name TempF=" . sprintf ("%3.1f",$itemp); } elsif ($ib->family eq '10') { $itemp = read_temp $ib; print_log "DS1920: $object_name TempF=" . sprintf ("%3.1f",$itemp); } speak "app=weather The $object_name temp is " . int($itemp+.5) . " degrees"; } # Read the temp from all of the 1-wires # List all iButton temperatures. Note this can take a while, but there's no proxy support. $v_iButton_readtemps = new Voice_Cmd "Read all temp"; $v_iButton_readtemps-> set_info('Reads all temperature devices. Takes a while (.6 s per device)'); $v_iButton_readtemps -> set_authority('anyone'); if (said $v_iButton_readtemps) { # print_log "Reading iButton temperatures"; for $ib (@ib_sensors) { $object_name = $ib->{object_name}; if ($ib->family eq '26') { # for the DS2438s $itemp = &Read_DS2438Temp($ib); print_log "DS2438: $object_name TempF=" . sprintf ("%3.1f",$itemp); } elsif ($ib->family eq '10') { # for the DS1920s $itemp = read_temp $ib; print_log "DS1920: $object_name TempF=" . sprintf ("%3.1f",$itemp); } } } # Read the relative humidity (RH) from one 1-wire 2438 device $v_iButton_readhumDS2438 = new Voice_Cmd "Read humidity [1,2]"; $v_iButton_readhumDS2438 -> set_info('Read the humidity from a specific button'); $v_iButton_readhumDS2438 -> set_authority('anyone'); if ($state = said $v_iButton_readhumDS2438) { $ib = $ib_sensorsRH[$state - 1]; $itemp = &Read_DS2438RH($ib); $object_name = $ib->{object_name}; print_log "DS2438: $object_name RH=" . sprintf ("%3.1f",$itemp); speak "app=weather The $object_name humidity is " . int($itemp+.5) . " percent"; } # List all iButton humidity. Note this can take a while, but there's no proxy support. $v_iButton_readhumsDS2438 = new Voice_Cmd "Read all humidity"; $v_iButton_readhumsDS2438-> set_info('Reads all humidity devices. Takes a while (.6 s per device)'); $v_iButton_readhumsDS2438 -> set_authority('anyone'); if (said $v_iButton_readhumsDS2438) { #print_log "Reading iButton humidities:"; for $ib (@ib_sensorsRH) { $itemp = &Read_DS2438RH($ib); $object_name = $ib->{object_name}; print_log "DS2438: $object_name RH=" . sprintf ("%3.1f",$itemp); } } # Read the wet-ness (Vwet) from one 1-wire device $v_iButton_readwetDS2438 = new Voice_Cmd "Read wet [1]"; $v_iButton_readwetDS2438 -> set_info('Read the wetness from a specific button'); $v_iButton_readwetDS2438 -> set_authority('anyone'); # And the MH-THW monitors whether it's wet or not, to warn me if something's wrong with the pump # command now set elsewhere in the Alarms function (triggers.pl) to run voice command. Easier to adjust than changing the code when I need to if ($state = said $v_iButton_readwetDS2438) { for $ib (@ib_sensorsWet) { $itemp = &Read_DS2438Wet($ib); $object_name = $ib->{object_name}; print_log "DS2438: $object_name Wet: $itemp"; if ($itemp == 0) { # speak "The wire is not wet"; } elsif ($itemp == 1) { speak "app=weather Warning: $object_name water wire is disconnected"; } elsif ($itemp == 2) { speak "app=weather Warning: $object_name Water detected"; print_log "Warning: $object_name Water detected"; if ($config_parms{mail_home}) { &net_mail_send( subject => "Water Detected", text => "$object_name Water Detected", to => $config_parms{mail_home} ); } } elsif ($itemp == -1) { speak "app=weather Warning: $object_name Water Error state reported"; } else { speak "app=weather Warning: Error on $object_name"; if ($config_parms{mail_home}) { &net_mail_send( subject => "Water Detection Error", text => "$object_name Error", to => $config_parms{mail_home} ); } } } } sub Read_DS2438Temp { my ($sensor) = @_; $object_name = $sensor->{object_name}; my $DS2438_tempF; my $DS2438_tempC; $DS2438_tempC = $sensor->Get_Temp_2438; #read DS2438 temp in Celsius if ($DS2438_tempC) { $DS2438_tempF = ($DS2438_tempC * 9)/5+32; # And return all values from whence we came return $DS2438_tempF; } else { return undef; } } sub Read_DS2438RH { my ($sensor) = @_; $object_name = $sensor->{object_name}; my $DS2438_tempC; my $DS2438_Vad; my $DS2438_Vdd; my $RH; $DS2438_tempC = $sensor->Get_Temp_2438; #read DS2438 temp in Celsius $DS2438_Vad = $sensor->Get_Vad_2438; #read DS2438 Vad $DS2438_Vdd = $sensor->Get_Vdd_2438; #read DS2438 Vdd # for some reason the VaD/Vdd values are sometimes strings. Make sure they're numbers #if (($DS2438_Vad) && ($DS2438_Vdd) && ($DS2438_tempC) && ($DS2438_Vad =~ /^[0-9]*$/) && ($DS2438_Vdd =~ /^[0-9]*$/)) { #if (($DS2438_Vad) && ($DS2438_Vdd) && ($DS2438_tempC) && (!($DS2438_Vad =~ /\D/)) && (!($DS2438_Vdd =~ /\D/))) { if (($DS2438_Vad) && ($DS2438_Vdd) && ($DS2438_tempC) && ($DS2438_Vad =~ /\D/) && ($DS2438_Vdd =~ /\D/)) { $RH = ((($DS2438_Vad/$DS2438_Vdd) - 0.16) / 0.0062) * (1.0546 - 0.00216 * $DS2438_tempC); # 161006 Fixed for if a negative value is returned if ($RH < 0) { $RH = 0; } return $RH; } else { print_log "DS2438: $object_name: TempC:$DS2438_tempC Vad: $DS2438_Vad Vdd: $DS2438_Vdd"; # for debugging return undef; } # And return all values from whence we came } sub Read_DS2438Wet { my ($sensor) = @_; my $object_name = $sensor->{object_name}; $itemp = $sensor->Get_Vwet_2438; #read DS2438 Vwet return $itemp; } # Next was getting rrd to work. # first, I pulled rrd from ppm # ppm # install RRD-Simple # install rrd.ppm # and installed RRD from http://oss.oetiker.ch/rrdtool/ # and populated all of the rrd environment variables in mh.private.ini #rrd_dir=e:/rrd #weather_data_csv=$config_parms{data_dir}/rrd/environ.csv #weather_data_rrd=$config_parms{data_dir}/rrd/environ.rrd #@ The location where the graphs are to be stored [$config_parms{data_dir}/rrd] #weather_graph_dir = $config_parms{data_dir}/rrd/graphs #@ The Footer to be used on all the graphs [Last updated $Time_Date, copyright www.domotix.net] #weather_graph_footer = Last updated $Time_Date, copyright www.sinister.net #@ How often in minutes to update the graph [10] #weather_graph_frequency = 30 #@ Skip generation graphs for specific periods, blank to generate graphs for all periods #weather_graph_period_skip = 2month 6month 1year 2year 5year #@ Skip generation graphs, blank to generate all the graphs, possible values : tempout tempin windspeed winddir raintotal rainrate press humout humin #weather_graph_skip = windspeed winddir raintotal rainrate # Web dir for PNG graph file #html_alias_rrd = $config_parms{data_dir}/rrd/graphs #weather_rrd_format = PNG # PNG / GIF (PNG is default) # - Sensor name for indoor temperature and humidity graphs #weather_graph_sensor_names = intemp => Average Indoor Temp, inhumid => Average Indoor Humidity, tempspare1 => Water Sensor, tempspare2 => Computer Room, tempspare3 => Back Crawl Space, humidspare1 => Water Sensor, humidspare2 => Computer Room, humidspare3 => Back Crawl Space # Values : sensor names = intemp, tempspare1,..., tempspare10, inhumid, # humidspare1,...,humidspare10 # And activated code/common/weather_rrd_update.pl # and it created the database my $temp_avg; my $humid_avg; my @old_humid; $v_iButton_setWeather = new Voice_Cmd "Update iButton Data"; $v_iButton_setWeather-> set_info('Updates the iButton variables'); $v_iButton_setWeather -> set_authority('anyone'); # Done as a voice command so the update interval can be set as a trigger, instead # of hard-coded if (said $v_iButton_setWeather || $Startup || $Reload) { &setWeather; } sub setWeather { # updates the %Weather hash for known values from the iButton devices. # this way these items can be graphed as the temp values used by weather_rrd_update.pl # Get the temp states my $new_temp_avg; my $new_humid_avg; my $sensor; my $tempsensor; my $humidsensor; my $sensorsfound; my $counter; $new_temp_avg = 0; $sensor = 0; $counter = 0; for my $i (0..$#ib_sensors) { $ib = $ib_sensors[$i]; $object_name = $ib->{object_name}; if ($ib->family eq '26') { # for the DS2438s $itemp = &Read_DS2438Temp($ib); } elsif ($ib->family eq '10') { # for the DS1920s $itemp = read_temp $ib; } $sensor = $i + 1; $tempsensor = 'TempSpare'."$sensor"; if ($itemp) { # Make this error resistant by not replacing when it's zero $Weather{$tempsensor} = sprintf("%3.2f", $itemp); $new_temp_avg += $itemp; $counter++; } else { #$new_temp_avg += $Weather{$tempsensor}; } } #$new_temp_avg = $new_temp_avg / ($#ib_sensors + 1); $new_temp_avg = $new_temp_avg / ($counter); $Weather{'TempIndoor'} = sprintf("%3.2f", $new_temp_avg); # Get the humid States $new_humid_avg = 0; $sensor = 0; $sensorsfound = 0; for my $i (0..$#ib_sensorsRH) { $ib = $ib_sensorsRH[$i]; $object_name = $ib->{object_name}; $itemp = &Read_DS2438RH($ib); $sensor = $i + 1; $humidsensor = 'HumidSpare'."$sensor"; if ($itemp) { $Weather{$humidsensor} = sprintf("%3.2f",$itemp); $old_humid[$sensor] = $Weather{$humidsensor}; $new_humid_avg += $itemp; $sensorsfound++; } else { #$humid_avg += $Weather{$humidsensor}; if ($old_humid[$sensor]) { $Weather{$humidsensor} = sprintf("%3.2f",$old_humid[$sensor]); } } } if ($sensorsfound) { #$humid_avg = $humid_avg / ($#ib_sensorsRH + 1); $new_humid_avg = $new_humid_avg / ($sensorsfound); $Weather{'HumidIndoor'} = sprintf("%3.2f",$new_humid_avg); $humid_avg = $new_humid_avg; } else { $Weather{'HumidIndoor'} = sprintf("%3.2f",$humid_avg); } }
weather_tempin_1week.png
(image/png, 123.7 KB) - not displayed