User avatar
BAStumm
Posts: 134
Joined: Fri Aug 23, 2013 3:37 pm
Location: Loon Lake, WA USA
Contact: Website

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Thu Mar 27, 2014 4:22 pm

I'm dealing with industrial ovens that operate at temperatures in excess of 300 degrees C (or more than 600F). Cost isn't that high, about $3 per T/C with a 3 meter lead. The mod-tc-mk2 is $15. I'd probably go a different route if I didn't need the temperature rating.

User avatar
iinnovations
Posts: 621
Joined: Thu Jun 06, 2013 5:17 pm

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Thu Mar 27, 2014 7:54 pm

BAStumm wrote:I'm dealing with industrial ovens that operate at temperatures in excess of 300 degrees C (or more than 600F). Cost isn't that high, about $3 per T/C with a 3 meter lead. The mod-tc-mk2 is $15. I'd probably go a different route if I didn't need the temperature rating.
Exactly. That's the 5% of applications where you need that. I've definitely used them to build furnaces before, but avoid them wherever I can. I think there's also an extended cost with the IO you need, special wiring, and ... well, time.
CuPID Controls :: Open Source browser-based sensor and device control
interfaceinnovations.org/cupidcontrols.html
cupidcontrols.com

User avatar
BAStumm
Posts: 134
Joined: Fri Aug 23, 2013 3:37 pm
Location: Loon Lake, WA USA
Contact: Website

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Thu Mar 27, 2014 8:01 pm

The MOD-TC I use is I2c and I use 6+ of these devices per oven (multi-zone ovens for solder reflow if you are familiar with that). At each heat zone I have a single device that reports back temperature and wattage while performing PID closed loop control of either temperature or wattage (depending on application). All the boards are on the same bus so it is kind of nice to have the analog and digitial I/O distributed like this.

User avatar
iinnovations
Posts: 621
Joined: Thu Jun 06, 2013 5:17 pm

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Thu Mar 27, 2014 9:43 pm

Sounds like a good application, and much more elaborate than my reflow setup. I use an SPI thermocouple for mine. Not elegant, for sure: http://www.cupidcontrols.com/2013/12/ho ... -a-budget/

I'd definitely go mcu if and when I upgrade. I'll probably invest in having boards made with parts placed instead.
CuPID Controls :: Open Source browser-based sensor and device control
interfaceinnovations.org/cupidcontrols.html
cupidcontrols.com

User avatar
BAStumm
Posts: 134
Joined: Fri Aug 23, 2013 3:37 pm
Location: Loon Lake, WA USA
Contact: Website

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Fri Mar 28, 2014 6:11 pm

These are not home-brew reflow ovens. I work for an oven manufacturer.

karlpap
Posts: 2
Joined: Sun Jun 08, 2014 4:58 pm

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Mon Jan 05, 2015 3:03 pm

When using a Raspberry Pi, HA7 and DS18B20 where to connect the various pins?
ie where to connect the HA7 pins VCC, GND, TX, RX, DW and DW-GND
and the DS18B20 pins GND, DQ and Vdd
Any help greatly appreciated.

wayner
Posts: 84
Joined: Thu Oct 25, 2012 1:40 am
Location: Toronto, Ontario, Canada

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Mon Jan 05, 2015 9:10 pm

@karlpap - Try googling "raspberry pi temperature sensor" Your first hit should be a page from Cambridge university that shows the wiring. And lots more...

@everyone in this thread:
Why manually put the modprobe commands in all of your code to read the DS18B20 sensors? Why not add the modprobe commands to your /etc/modules file like this:

Code: Select all

w1-gpio  
w1-therm  
And you never need to think of them again. They will automatically load at bootup.

anita2r
Posts: 226
Joined: Sun Dec 23, 2012 6:55 pm
Location: Ottawa, Canada

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Mon Jan 05, 2015 9:14 pm

karlpap wrote:When using a Raspberry Pi, HA7 and DS18B20 where to connect the various pins?
ie where to connect the HA7 pins VCC, GND, TX, RX, DW and DW-GND
and the DS18B20 pins GND, DQ and Vdd
Any help greatly appreciated.
The HA7s has 6 connections:
  • pin 1 - marked with a dot is 3.3v supply
    pin 2 is ground
    pin 3 is Transmit (Tx)
    pin 4 is Receive (Rx)
    pin 5 is 1-wire network data
    pin 6 is 1-wire network ground
The 1-wire network can be parasitically powered by the HA7s, or a 3.3v line can be connected to the third pin (Vdd)
on each DS1820 temperature sensor.
pins 5 & 6 on the HA7s should be connected to the DS18B20's using a twisted wire pair

The Tx and Rx pins are connected to the Raspberry Pi's UART
Connect Tx to header pin 10 - the Rx pin
Connect Rx to header pin 8 - the Tx pin

The Raspberry Pi's UART is /dev/ttyAMA0

These are the notes I made when I first used the Pi's UART:
(vim is the text editor I used - use whatever you are comfortable with)
The UART on the Raspberry Pi is tied to the console so that boot commands are available on it.
To use it for other purposes, including this communication with the HA7s, the console connection must be removed.
Follow these steps:
The file /boot/cmdline.txt contains the following:
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
Make a backup of the file before editing it:
sudo cp /boot/cmdline.txt /boot/cmdline_backup.txt
Edit the cmdline.txt file:
sudo vim /boot/cmdline.txt
delete the two parameters involving the serial port (ttyAMA0) to get the following:
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
Edit the file: /etc/inittab
sudo vim /etc/inittab
comment out the following line:
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
write & quit
Reboot:
sudo reboot
Find the serial device name:
dmesg | grep tty
identified serial device ttyAMA0

Make yourself the owner of the device
sudo chown <username>:tty /dev/ttyAMA0
see udevRules.txt for how to make this change occur at every boot
(alternatively add <username> to the tty group - not tested but may be better)

The Raspberry Pi's UART (/dev/ttyAMA0) must be initialized before use:
settings are 8 bits, 1 stop & no parity - matching the HA7s serial connection
How you do this depends on what serial program you use. Mine is all done using a Perl script
with the Perl module Device::SerialPort

Hope this helps.

Regards

anita2R
(if you decide to use Perl I can post my Perl script)

karlpap
Posts: 2
Joined: Sun Jun 08, 2014 4:58 pm

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Tue Jan 06, 2015 1:16 am

Thank you for the detailed (and quick) answer.
I would appreciate your perl code.

chrisepworth
Posts: 8
Joined: Sat Jul 12, 2014 11:46 pm

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Tue Jan 06, 2015 5:39 am

Hi Guys, I am trying to get this to work but really bad at understanding bash files etc.

At this stage I can read all the temps on my board but would like to see them on a screen like cacti graphs or something similar.

Can someone point me in the right direction with full step by step guide to getting this working.

Cheers

Chris Epworth

anita2r
Posts: 226
Joined: Sun Dec 23, 2012 6:55 pm
Location: Ottawa, Canada

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Tue Jan 06, 2015 5:51 am

karlpap wrote:I would appreciate your perl code.
Hi,

To put the Perl script into context:

1. The data files for holding the results are in a folder /var/1w_files
You can use any folder that suits you, but you will need to change the path in the script.
2. The ID's of the temperature sensors are shown in most Raspberry Pi documentation in the following format:
28-0000018a36db
I don't know why this was done, as the actual ID is like this:
530000018A36DB28
The first two hex characters '53' in this example are a check character, and as you can see, the family code, '28' for the 1-wire temperature sensors I use, comes at the end.

Because I had already been using the Pi's 1-wire system and had data stored in files named like 28-0000018a36db, I included a conversion routine to get the Pi format from the 'real' Maxim's sensor format.

3. Reading a group of sensors
In Maxim's documentation and available through the HA7s is a method for finding all sensors in a specific family that are attached to the 1-wire network. This means that before reading temperature sensor data you need a step to find the ID's of the attached sensors.
As I only rarely change or add sensors, I decided that I would just keep the ID's in a file, and access the file from the Perl script. A new or changed sensor is handled by editing the file. The file is also in the /var/1w_files folder and is named romIds.txt
I contains one rom Id per line like this:
DF0000041875D028
6E0000018A3B3028
660000018A4BE828
D700000418759C28

You will see that rather than address each sensor individually and send a 'convert temperature' request to each one, I use the
skip rom and convert temperatures command as part of the initialization. This makes all sensors prepare a digital value for their own temperature reading, and then you only need address each sensor once, to get its temperature. This is all documented in the Maxim literaure. It took me quite a while to understand the commands, but it was worth the effort (I think).

4. Output is to simple text files in the /var/1w_files folder. The files are named using the Pi's format:
/var/1w_files/28-0000018a36db
There is one reading per line in the format:
05-01-2015 23:40:11 21937.5
The date, time and temperature reading are separated by spaces, which makes it easy to handle later on using standard Linux bash script and other utilities. I use gnuplot for creating charts of the data and this format works well.

As before, I have kept to the Pi's strange format of reporting temperature x 1000. My script converts to this 'standard' just for compatibility with data I had collected using the Pi's 1-wire system. If starting afresh, there is no need for this conversion.

5. Error logging
You will see that I log errors. This has helped identify parts of the 1-wire network that need attention, also it identified that my battery-operated Pi had most errors when the battery charger came on-line - so I added some smoothing etc. to the circuit. The errors are logged to /var/1w_files/err2.log.
Lines look like this:
28-00000418759c 04-01-2015 15:49:14 err#2
28-00000418759c 04-01-2015 15:49:15 err#2
28-00000418759c 04-01-2015 15:49:15 err#2
28-00000418759c 04-01-2015 15:49:15 err#3
(this sensor gives me most of my errors and tells me that I need to work on it - so far not sure why, but it is adjacent to the main power feed to the house, so perhaps EMF 'noise')

6. Perl
Before using the Perl script there are two modules that need to be installed:
Device::SerialPort;
Time::HiRes qw(usleep);
I use cpan to install them - rather slow, but it works:
At command prompt enter: cpan
At cpan prompt enter: install Device::SerialPort
and when installed enter: install Time::HiRes
When Time::HiRes installation is complete enter: quit

7 The script
The script is called from root's cron
Enter sudo crontab -e
Add the following lines to it, then save and exit
# poll all temperature sensors every 5 minutes
*/5 * * * * /home/<username>/rdHA7s.pl >>/home/cron_output/cron_log 2>&1
Obviously change <username> to your name or change the path to wherever you put your Perl script.
As you can see there is a log file to hold any output from cron, in case of errors.

After all that rambling, here is the script. It has a fair bit of documentation in it, but feel free to ask for further clarification.

Code: Select all

#!/usr/bin/perl
#
# rdHA7s.pl
# Version 1.32
#
# A script to read and save temperature readings from all the group 28 
#   1-wire temperature sensors#
# This script is called every 5 minutes by sudo's crontab
# Running as sudo avoids having to change ownership of /dev/ttyAMA0
#  after each reboot
#
use Device::SerialPort;
use Time::HiRes qw(usleep);
use strict;
#
# variables
my ($port, $resp);              # serial port name, response returned by a read
my ($id, $xid);                 # device id, extended id
my ($temp, $dtTmStamp);         # device id, temperature, date/time stamp
my ($firstLtr, $tBytes);        # 1st letter of write command,  two temperature bytes from response
my ($longDelay, $shortDelay);   # different delays according to 1-wire command
my ($rRead, $rRdCnt, $err);     # flag to stop re-reads, re-read count & error id
my ($maxRead, $fName);          # serial read maximum time allowed, output data file name
my ($startTime, $loop);         # controls for main data gathering loop
my ($wait);                     # wait duration after error - 100000 = 1 second
my ($n, $ret);                  # general loop counter, dummy return value for keep-alive call
# arrays
my (@initCmds, @romIds, @temperatures, @id_data);
#
# setup delays
# long delay for R and W commands
$longDelay=0.4;
# short delay for other commands
$shortDelay=0.2;
# delay before re-try after error
$wait=150000;
#
# setup serial port to be used
$port = Device::SerialPort->new("/dev/ttyAMA0");
#
# initialize port
$port->databits(8);
$port->baudrate(9600);
$port->parity("none");
$port->stopbits(1);
$port->write_settings;
#
# get list of ROM ID's to use
open (IDLIST, "/var/1w_files/romIds.txt");
$n=0;
while (<IDLIST>) {
        # get valid ROM ID's from file
        # each starts with a crc and ends with a family code
        chomp $_;
        $romIds[$n]=$_;
        $n++;
}
close (IDLIST);
#
# initial command sequences with length of responses
#   Reset, Skip rom & Convert temperatures
@initCmds = ("R",1, "W01CC\r",2, "W0144\r",2);
#
# use initial commands
&initHA7s();
#
# only let this part of the script run for a maximum of 1 minute
# set start time & loop flag
$startTime=time();
$loop=1;
while (time() < $startTime + 60 && $loop) {
# loop through all device rom IDs
#  to address them and get scratchpad data with temperatures
foreach (@romIds) {
        $rRead = 1;
        $rRdCnt = 0;
        while ($rRead) {
                # get date/time stamp - we need this now in case of error
                $dtTmStamp=&dttmStamp;
                # keep a copy of the id
                $id=$_;
                # create Address command ('A' + rom ID + return)
                $xid="A$_\r";
                # write Address
                &writePort($xid);
               # read response - returns rom ID
                $resp=&readPort($id, 18);
                # test if returned rom id matches requested rom id
                if (substr($resp,0,16) ne "$id") {
                        # error
                        # log it as err#4
                        $err = "err#4";
                        $id=&reFmtRom($id);
                        &errLog($id, $dtTmStamp, $err);
                        #exit
                        exit 1;
                } else {
                # rom ID matches - so process it
                # request scratchpad data (9 bytes)
                &writePort("W0ABEFFFFFFFFFFFFFFFFFF\r");
                # read response - returns temperature in bytes 1 & 2
                $resp=&readPort("W0ABEFFFFFFFFFFFFFFFFFF\r", 22);
                # reformat rom ID to be compatible with Pi's format
                #  e.g. 28-0000018a29ee (family code first, lower case & no crc)
                $id=&reFmtRom($id);
                #
                # check crc of scratchpad data - in byte 9
                $resp=&crcChk($resp);
                # test for crc check digit error
                if($resp ne "Error"){
                        #  no error so convert 1st two scratchpad bytes to a temperature
                        $tBytes=substr $resp,2,4;
                        $temp=&convT($tBytes);
                        # check returned temperature for error message
                        if (($temp eq "Error")){
                                # invalid temperature error
                                $err ="err#2";
                                # log error
                                &errLog($id, $dtTmStamp, $err);
                                $rRdCnt++;
                                usleep($wait);
                        }
                        #
                       } else {
                        # crc error
                        $temp = "Error";
                        $err = "err#1";
                        # log error
                        &errLog($id, $dtTmStamp, $err);
                        $rRdCnt++;
                        usleep($wait);
                }
                if ($temp == "Error") {
                        # error - so test number of re-reads
                        if ($rRdCnt == 3) {
                                # error code #3 = unrecoverable error
                                $err = "err#3";
                                # log error
                                &errLog($id, $dtTmStamp, $err);
                                # save temperature as 'Error' ($temp = 'Error')
                                # save data - rom ID, time stamp and the temperature to an array
                                push (@temperatures, "$id#$dtTmStamp $temp");
                                # flag to stop re-reads
                                $rRead = 0;
                                }
                        } else {
                        # no error - so log and exit 'this' read
                        # save data - rom ID, time stamp and the temperature to an array
                        push (@temperatures, "$id#$dtTmStamp $temp");
                        # flag to stop re-reads
                        $rRead = 0;
                }
                }
        }
}
# we have got to end of data collection - so can exit loop even if not timed out
$loop=0;
}
#
# save data collected in array to individual device files
foreach (@temperatures){
        # split each array element at '#'
        # id before '#' and data after '#'
        @id_data=split(/#/);
        # ID is filename - add it to path
        $fName="/var/1w_files/". $id_data[0];
        # open the data file for writing (append)
        open (DATAOUT, '>>', $fName);
                # add data to file
                print DATAOUT "$id_data[1]\n";
        close (DATAOUT);
}
#
exit 0;
#########################################################################
#
# subroutines and functions
#
#########################################################################
# write to port
sub writePort{
        # write command passed as a parameter
        my ($Cmd) = @_;
        # purge the receive buffer before we send a command
        $port->purge_rx;
        # write to port
        $port->write($Cmd);
}
#########################################################################
# read from port
sub readPort {
        # write command & length of data to be read passed as parameters
        my ($Cmd, $Len) = @_;
        # variables
        my ($sData, $Delay);
        my ($Second, $Minute, $Hour, $Day, $Month, $Year);
        #
        # clear buffers
        $port->lookclear;
        # get first letter of command
        $firstLtr=substr $Cmd,0,1;
        # delay after write - depends on command - W & R need longer
        if (($firstLtr eq "R") || ($firstLtr eq "W")){
                $Delay=$longDelay;
                } else {
                $Delay=$shortDelay;
        }
        # delay
        select(undef,undef,undef,$Delay);
        #
        # read from serial port
        $sData = "";
        # stop read wait if > 10 seconds
        $maxRead = time + 10;
        #
        until ("" ne $sData || time > $maxRead) {
                # wait for correct response length
                $sData = $port->read($Len);
        }
        # As 'R' (reset) has no returned data, return 'Reset'
        if ($firstLtr eq "R"){
                return("Reset");
                } else {
                return($sData);
        }
}
##########################################################
# subroutine to send all initialization commands
sub initHA7s {
        for ($n=0; $n<=scalar(@initCmds)-2; $n+=2){
                # write command - send command to write subroutine
                &writePort($initCmds[$n]);
                # read response
                $resp=&readPort($initCmds[$n], $initCmds[$n+1]+2);
        }
}
##########################################################
# Date stamp function
sub dttmStamp {
        # no parameters passed to this function
        # variables
        my ($Year, $Month, $Day, $Hour, $Minute, $Second);
        my $dtStamp;
        #
        # get raw date & time data
        ($Second, $Minute, $Hour, $Day, $Month, $Year) = localtime(time);
        # convert year and month
        $Year += 1900;
        $Month++;
        # create the date, time stamp string
        $dtStamp=sprintf("%02d-%02d-%04d %02d:%02d:%02d",$Day,$Month,$Year,$Hour,$Minute,$Second);
        #
        return ($dtStamp);
}
##########################################################
# Convert temperature function
# returns value as t*1000 to match
#   format used by Raspberry Pi e.g 46.812 C is 46812
sub convT {
        # temperature passed to this function as a parameter
        #   two bytes in LSB, MSB order
        my ($hex) = @_;
        # make sure the parameter is treated as a hex number
        $hex=hex($hex);
        # variables
        my ($hexML, $Sign, $Mult, $Ctemp);
        # set multiplier - change to 0.0625 to return actual temp
        $Mult=62.5;
        #
        # change to MSB, LSB order (16 bit numbers)
        $hexML= unpack('n', pack('v', $hex));
        #
        # determine sign from most significant bit
        # mask off all but highest bit
        if ($hexML & 0x8000) {
                # most sig. bit is 1, (negative number)
                $Sign="-";
                }
                else
                {
                # most sig bit is 0, (positive number)
                $Sign="+";
        }
        # either use value as is (+ve) or do a 2's complement (-ve)
        # first mask off 5 highest bits - keep lowest 11 bits
        $hexML=$hexML & 0x07FF;
        if ($Sign eq "+"){
                # +ve so just multiply
                $Ctemp=$hexML * $Mult;
                }
                else {
                # -ve so 2's complement
                # complement
                $Ctemp = ~$hexML;
                # add one
                $Ctemp++;
                # we only want the lowest 11 bits (of the 64 used)
                $Ctemp=$Ctemp & 0x000007FF;
                # and multiply
                $Ctemp=$Ctemp * $Mult;
                # add '-' sign
                $Ctemp=$Sign . $Ctemp;
        }
        # test temperature value
        # -62500 & 85000 are not valid
        if ($Ctemp eq "-62500" || $Ctemp eq "85000"){
                #error
                $Ctemp = "Error";
        }
        return($Ctemp);
}
##########################################################
# Re-format ROM code function
sub reFmtRom {
        # reformat the ROM ID code to match format used
        # on Raspberry Pi e.g. 28-0000018a51a7
        # also ensures that hex characters are lower case
        # original ROM ID passed as a parameter
        my ( $rom ) = @_;
        # variables
        my $fId;
        #
        $fId = (substr $rom, -2,2) . "-" . (substr $rom, 2,12);
        return(lc($fId));
}
##########################################################
# crc check function
sub crcChk {
        # Function computes crc from 8 bytes of scratchpad data
        #  and compares it to 9th byte (transmitted crc)
        # Returns "Yes" if crc OK, else returns "No"
        #
        # Command code 'BE', 8 bytes of data and 1 byte crc 
        #  are passed as a single parameter to this function 
        my ($Data) = @_;
        #
        # variables
        my ($byte, $crc, $bit, $test);
        my ($i, $n);
        #
        # set initial crc value to zero
        $crc = 0b00000000;
        #
        # main loop - takes 8 bytes of scratchpad data 
        #  bytes are in positions 2/3 through 17/18 (zero based)
        #  positions 0/1 contain the command byte BE
        for ($i=2; $i<=17; $i+=2) {
                #convert pairs of hex digits into number
                $byte=hex(substr $Data, $i, 2);
                # sub-loop to read 8 bits from byte (LS bit first)
                for ($n=0; $n<=7; $n++){
                        #
                        # get LS bit of byte by applying mask
                        $bit = $byte & 0b00000001;
                        #
                        # exclusive OR the LS bit of the crc with the current data bit
                        $test = $crc ^ $bit;
                        # apply mask to get LS bit only
                        $test = $test & 0b00000001;
                        #
                        # test if result was 1 or 0
                       if ($test) {
                                #
                                # result was 1 so need to XOR, right shift &  make MS bit 1
                                #
                                # XOR crc with 0b00011000
                                $crc = $crc ^ 0b00011000;
                                # right shift
                                $crc = $crc >> 1;
                                # make MS bit 1 by OR'ing with 0b10000000
                                $crc = $crc | 0b10000000;
                                }
                                else {
                                #
                                # result was zero, so just right shift crc (MS bit will be 0)   
                                $crc = $crc >> 1;
                        }
                        # shift data byte to right so next bit is in LS bit position
                        $byte = ( $byte >> 1 );
                }
        }
        # compare calculated crc to transmitted crc
        if ($crc == hex(substr $Data, 18, 2)){
                return($Data);
                }
                else {
                return("Error");
        }
}
##########################################################
# log error to file
sub errLog{
        # ID, date/time stamp and error code are passed as a single parameter to this function 
        my ($eId, $eDtTmStamp, $eErr) = @_;
        # append information to end of error log
        open (DATAOUT, '>>', '/var/1w_files/err2.log');
                # add date/timestamp, device ID and error code
                print DATAOUT "$eId $eDtTmStamp $eErr\n";
        close (DATAOUT);
}
##########################################################
Regards

anita2R

anita2r
Posts: 226
Joined: Sun Dec 23, 2012 6:55 pm
Location: Ottawa, Canada

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Tue Jan 06, 2015 6:18 am

chrisepworth wrote:Hi Guys, I am trying to get this to work but really bad at understanding bash files etc.

At this stage I can read all the temps on my board but would like to see them on a screen like cacti graphs or something similar.

Can someone point me in the right direction with full step by step guide to getting this working.

Cheers

Chris Epworth
Have a look at this:http://www.raspberrypi.org/forums/viewt ... 70#p242370
gnuplot works fine and if you create charts in png format, just push them into a folder for your webserver to display on a web page.

See attachment for sample gnuplot chart generated automatically.

Regards

anita2R
Attachments
IO-Temp_Chart.png
IO-Temp_Chart.png (43.98 KiB) Viewed 5002 times

chrisepworth
Posts: 8
Joined: Sat Jul 12, 2014 11:46 pm

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Wed Jan 07, 2015 11:02 pm

anita2r wrote:
chrisepworth wrote:Hi Guys, I am trying to get this to work but really bad at understanding bash files etc.

At this stage I can read all the temps on my board but would like to see them on a screen like cacti graphs or something similar.

Can someone point me in the right direction with full step by step guide to getting this working.

Cheers

Chris Epworth
Have a look at this:http://www.raspberrypi.org/forums/viewt ... 70#p242370
gnuplot works fine and if you create charts in png format, just push them into a folder for your webserver to display on a web page.

See attachment for sample gnuplot chart generated automatically.

Regards

anita2R
Hi Anita2R,

do you have a tutorial on getting the one wire temp sensors working, logging them to a Db and then graphing them. Your script seems to capture multiple DS18B20 one wire devises in one script. but due to a lack of experience and knowledge I cant work out where to put the scripts etc.

Cheers

Chrisepworth

User avatar
iinnovations
Posts: 621
Joined: Thu Jun 06, 2013 5:17 pm

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Wed Jan 07, 2015 11:13 pm

Anita,

Why not use owfs?

Colin
CuPID Controls :: Open Source browser-based sensor and device control
interfaceinnovations.org/cupidcontrols.html
cupidcontrols.com

chrisepworth
Posts: 8
Joined: Sat Jul 12, 2014 11:46 pm

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Thu Jan 08, 2015 12:02 am

iinnovations wrote:Anita,

Why not use owfs?

Colin
Hi Colin, do you have some good tutorial on getting a newbie started with this.

anita2r
Posts: 226
Joined: Sun Dec 23, 2012 6:55 pm
Location: Ottawa, Canada

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Thu Jan 08, 2015 5:44 pm

chrisepworth wrote:Hi Anita2R,

do you have a tutorial on getting the one wire temp sensors working, logging them to a Db and then graphing them. Your script seems to capture multiple DS18B20 one wire devises in one script. but due to a lack of experience and knowledge I cant work out where to put the scripts etc.

Cheers

Chrisepworth
This is a link to where I started with 1-wire, just over 2 years ago http://www.raspberrypi.org/forums/viewt ... 26#p240926This shows what went where.
Since then I have developed: moving my sensors to a device (the HA7s) that handles the 1-wire timing and control, changing from bash scripts to Perl, adding error handling and error logging and steadily improving reporting systems.

Not only do I get a daily report on a web page with charts and statistics for the past 24 hours, but I can call up charts or statistics for defined periods, say the last 48 hours, or between set dates.
I just called for the outside temperatures from the start of the year:
  • Outside temperature statistics for:
    Thursday 01 January to Thursday 08 January 2015
    Maximum 0.38 C
    Minimum -26.62 C
    Average -11.33 C
    Delta 27.00 C
and for the same period last year:
  • Outside temperature statistics for:
    Wednesday 01 January to Wednesday 08 January 2014
    Maximum 3.88 C
    Minimum -25.94 C
    Average -14.46 C
    Delta 29.81 C
(Sorry some of the formatting got lost when posting to the forum)

iinnovations asks why I don't use owfs.
iinnovations wrote:Anita,

Why not use owfs?

Colin
Of course I could use owfs, but I started out with a system that was based on what was provided in Raspbian and it worked. The system works just fine, and I have been able to develop it as I needed.

Linux on a Pi is a great environment for learning. I only started using Linux 2 1/2 years ago, and have had Pi's for about 2 years. One thing I have learnt is that there are often many ways to do the same thing, so choose one that works for you.

I would not push my approach on anyone - I just post what has worked for me.
Look at owfs, and if that looks like an approach you want to take - go for it.

Regards

anita2R

rlust
Posts: 3
Joined: Thu Aug 30, 2012 4:22 pm

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Tue Dec 08, 2015 5:27 am

I love the work put into this script!

I know it should be simple but I keep having issues trying to modify the script.
How would I modify it to just write the temp to the file?
I am pulling it into node-red and am not having any luck in stripping out the data info so that I can convert to F.

Thanks for your great work here!

anita2r
Posts: 226
Joined: Sun Dec 23, 2012 6:55 pm
Location: Ottawa, Canada

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Tue Dec 08, 2015 4:15 pm

Hi,

First off, if you want temperatures in Fahrenheit, I suggest you modify the subroutine that calculates temperature: sub ConvT
A 'C to F' conversion can be added near the end.
As I mentioned earlier in the post, I kept the original Pi's format for temperatures which is 1000 * C (20100 is 20.1)
I don't know why it was setup that way, but for consistency of data, I kept it that way.
You don't need to do that, so change the variable $Mult from 62.5 to 0.0625
Add the C to F conversion when making the error check:

Code: Select all

        if ($Ctemp eq "-62.5" || $Ctemp eq "85"){
                #error
                $Ftemp = "Error";
                } else {
                # convert to F
                $Ftemp = ($Ctemp/5*9)+32;
        }
        return($Ftemp);
and return the Fahrenheit value rather than the original Celsius by changing return($Ctemp) to return ($Ftemp)
Edited post: also change $Ctemp = "Error"; to $Ftemp = "Error";
Declare the additional variable in the subroutine:
my ($hexML, $Sign, $Mult, $Ctemp);
becomes:
my ($hexML, $Sign, $Mult, $Ctemp, $Ftemp);

I haven't tested this because I don't want to have some of my data in F!, but I did get the perl script to print a Fahrenheit temperature using the extra code in the error check section, as shown above.

As to manipulating the data in the output files, the 'awk' function provides an easy way to get at each element of the data file
The default separator used by awk is a space, so you can get awk to return say the third element in each line, which is the temperature:

The data files have entries like this:
08-12-2015 09:21:49 9312.5
Assuming you have changed the temperature conversion subroutine as outlined above, the lines will look like this:
08-12-2015 09:21:49 48.7625
Run this bash script with a filename for your temperature sensor:

Code: Select all

#!/bin/bash
#
# A script to return the temperature values from a file named 28-0000018a29ee
#  in the /var/1w_files folder
# The file is a simple text file with lines of data like this:
#  08-12-2015 09:21:49 48.7625
# The temperature is the third element
awk '{print $3}' /var/1w_files/28-0000018a29ee
exit 0
You could use the line containing the awk command to push the temperature data into a new file, or into an array for further processing.
awk is more than a single function, it is a language with many commands. You could use it to do the C to F conversion without having to alter the original perl temperature subroutine:
awk '{print (($3/5000*9)+32)}' /var/1w_files/28-0000018a29ee

The default separator can be changed in awk, so that you could for instance retrieve the minutes from the data.
This line:
awk '{FS=":";$0=$0;printf "%02d\t",$2;FS=" ";$0=$0; print (($3/5000*9)+32)}' /var/1w_files/28-0000018a29ee
prints output like this:

Code: Select all

05	49.2125
The file separator was first set to ':' using FS=":";$0=$0
The $0=$0 resets awk to use the new separator
Later the separator is set back to a space: FS=" ";$0=$0
The printf command does not issue a newline, so we can print more than one value on a line and the \t inserts a tab
Also printf uses formatting instructions, in this case the "%02d" which formats the value to have a leading zero if it is less than two digits

As awk is being used in a bash script, the lines it produces can be sent to a new file:

Code: Select all

#!/bin/bash
#
FILEOUT="/path/to/file/ReFormat.txt"
awk '{FS=":";$0=$0;printf "%02d\t",$2;FS=" ";$0=$0; print (($3/5000*9)+32)}' /var/1w_files/28-0000018a29ee >>$FILEOUT
#
exit 0
You could alter the lines in the perl script which save the data - only retaining the temperature and dropping the date/time stamp, but in the long run it is likely better to retain the date/timestamp and just grab the temperature data from the output file.

Hope all this helps.

If you are using the HA7s, the following notes tell you how to get the romIDs of all the sensors.
Note that the romIds are not formatted in the same way the Pi displayed them when using the built-in 1-wire system.

1. Start minicom
enter 'minicom' (without the quotes)
This assumes that the default serial terminal has been disconnected from the Pi's system output
2. Check that the serial port settings are as follows:
9600 baud, 8 bits, no parity and 1 stop (8N1)
and the port is:
/dev/ttyAMA0
Use Minicom's menus to change these settings:
Enter Ctrl + A followed by 'o'
Use arrow keys to move to 'Serial port setup' & click 'Enter'
Select letters for settings to be changed
3. Return to minicom's main window and enter 'F28'
This is a call for id's of family 28 devices
This will return one ID
4. Enter 'f'
Each entry of 'f' will return another ID, until all family 28 devices have responded
5. The ID is returned as a single string of hex bytes
starting with two characters for the crc
and ending with the two byte family code '28'
6. To quit minicom, enter Ctrl + A then 'z' and select option 'Q' and accept

Regards

anita2R

anita2r
Posts: 226
Joined: Sun Dec 23, 2012 6:55 pm
Location: Ottawa, Canada

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Tue Dec 08, 2015 6:44 pm

Hello again,

Here is a short Perl script that will take a data file in the existing format (date time and temperature in C *1000)
and output just the Fahrenheit values to another file.

Code: Select all

#!/usr/bin/perl
#
use strict;
#
my ($dt, $tm, $Ctemp, $Ftemp);
#
# open data input file
open (INFILE, "<", "/var/1w_files/28-0000018a29ee");
# open output file for reformatted data (an empty file each time or use ">>" to append data)
open (OUTFILE, ">", "/path/to/file/ReFormat.txt");
# read in the data line by line, each line is in the perl variable $_
while (<INFILE>) {
        # data lines look like this: 08-12-2015 12:30:11 8875
        # split the data at spaces - getting 3 elements
        ($dt, $tm, $Ctemp) = split(/ /,$_);
        # the temperature value is now in the variable $Ctemp
        # convert temperature to Fahrenheit
        $Ftemp = ($Ctemp/5000*9) + 32;
        # output the converted temperature followed by a newline '\n' 
        print OUTFILE "$Ftemp\n";
}
close (OUTFILE);
close (INFILE);
#
exit 0;
As split is being used in its default configuration, i.e. splitting on spaces and using the $_ variable as the data source, you can shorten the line:
($dt, $tm, $Ctemp) = split(/ /,$_);
to:
($dt, $tm, $Ctemp) = split;

Regards

anita2R

User avatar
frazelle09
Posts: 70
Joined: Mon May 07, 2012 5:04 am
Location: Mexicali, Baja California, Mexico

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Thu Dec 10, 2015 7:05 pm

Hi guys! i have bee searching for the "image" that was supposed to be near the top of the thread, but haven't been able to find it. Has it been taken down? It would really be nice to have on of the wiring.

Have a great day! :)
"The earth is one country and mankind its citizens."
Bahá'u'lláh
"La tierra es un sólo país y la humanidad sus ciudadanos."

User avatar
frazelle09
Posts: 70
Joined: Mon May 07, 2012 5:04 am
Location: Mexicali, Baja California, Mexico

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Sun Dec 13, 2015 11:08 pm

o.k. Got some help from here... http://www.sbprojects.com/projects/rasp ... rature.php and now have a working Pi from which i can read my one DS1820 successfully. Yea!!!

Now we're searching for some way to upload this data, taken from readings every 5 minutes, to a webpage - website.

Have a great evening! :)

_____________________________________-
frazelle09 wrote:Hi guys! i have bee searching for the "image" that was supposed to be near the top of the thread, but haven't been able to find it. Has it been taken down? It would really be nice to have on of the wiring.

Have a great day! :)
"The earth is one country and mankind its citizens."
Bahá'u'lláh
"La tierra es un sólo país y la humanidad sus ciudadanos."

rfeyer
Posts: 102
Joined: Sun Nov 23, 2014 9:25 pm

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Mon Jan 18, 2016 2:18 pm

Knowing this is an old thread, it is exactly what I was looking for - though mostly above my head at this point.
However, the best building block I have read so far to what I am trying to accomplish (capturing data to a spreadsheet without using MySQL).

However, at it's basis, I do not full understand the grep usage, if someone could PLEASE elaborate. using it I see it gives only the 5 last digits of the temp sensot output following t3, but as much as I try to understand I can not see how it got there.
These are the notes I have so far on the grep command:
roomtemp=$(cat /sys/bus/w1/devicecs/28-0000072f9386/w1_slave | grep -E -o ".{0,0}=.{0,5}" | cut -c 3-)

-E show only as regular extended expression
-o show only the part of the line which matches
{n,m} The preceding item is matched at least n times, but not more than m times.

biggest confusion is the {0,0} and I could not find anything explaining the cut command - and why it is actually needed.

ANy help would be appreciated,
Rainer

User avatar
rpdom
Posts: 15030
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Mon Jan 18, 2016 2:28 pm

Try the command in stages and see what each bit does.

(I think there may be a typo. Shouldn't it be ".{0,0}t=.{0,5}" on the grep?)

I don't know what the ".{0,0}" is in there for either, but here goes with breaking it down.

Code: Select all

[email protected] ~ $ cat /sys/bus/w1/devices/28-00044a1f53ff/w1_slave 
27 01 55 00 7f ff 0c 0c 8e : crc=8e YES
27 01 55 00 7f ff 0c 0c 8e t=18437
[email protected] ~ $ cat /sys/bus/w1/devices/28-00044a1f53ff/w1_slave | grep -E -o "t=.{0,5}"
t=18437
[email protected] ~ $ cat /sys/bus/w1/devices/28-00044a1f53ff/w1_slave | grep -E -o "t=.{0,5}" | cut -c 3-
18437
The cut gets rid of the "t=" in front of the result of the grep.

rfeyer
Posts: 102
Joined: Sun Nov 23, 2014 9:25 pm

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Mon Jan 18, 2016 2:49 pm

rpdom,TY again for the fast reply - I did as you suggested and executed the statement piece by piece - that was extremely helpful.
To, if the cut -3 cutes the t3, and t3 are only two characters, whyt does it work with cut -3?

User avatar
rpdom
Posts: 15030
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: TUTORIAL: DS18B20 temp sensor. No C or Python!!! Cost: $

Mon Jan 18, 2016 7:14 pm

There are two parameters being supplied to the cut command. The first is "-c" which means "cut the line at these columns.

The second part of that is a list of columns (character positions) to use. "3-" means "From column 3 until the end of the line", which has the effect of dropping columns 1 and 2, which are the "t=" characters.

Here's an example of another column list in cut:

Code: Select all

[email protected] ~ $ echo "abcdefghijklmnopqrstuvwxyz" | cut -c 1-3,24-
abcxyz
"Cut columns from 1 to 3, and from 24 to the end of the line"

Return to “Automation, sensing and robotics”