1-wire library on Yun

Hi, just trying to get the 1-wire example sketch working on the Yun (after loading the 1-wire library from here):

http://www.pjrc.com/teensy/td_libs_OneWire.html

The example sketch is File->Examples->OneWire->DS18x20_Temperature.ino

I have used the Yun temperature example sketch:

File->Examples->Bridge->TemperatureWebPanel.ino

and inserted the one wire code into it, with 1-wire temp sensor hooked up to D2 (this works fine on my Nano).

It seems to kill the web display in my browser, and I have isolated the problem to the point where this happens:

ds.reset(); ds.select(addr); ds.write(0x44, 1); // start conversion, with parasite power on at the end

Does anyone out there know why it won't work, or has anyone seen a 1-wire library that will work with the Yun?

So far the Yun is working well, very cool to program it over wifi, but I'm stuck at this point.

Tks!

From your information, I am afraid I can not tell what the problem is, but I wanted to mention, that this is exactly the library I use to read my DS18B20 sensors.

Hi @bjarne, thanks for your reply. Do you mean that you are using that library with the Yun?

Yes !!

ok, thank you, that is very helpful info because it eliminates the possibility that there is a problem with the library. By any chance, did you find a test example sketch that will work for 1-wire and the Yun?

Tks, ab

I can’t remember exactly which sketches I used for my initial testing, but here is the sketch I use for discovering the sensor addresses, it might help you establish a starting point (it works with the www stuff from TemperatureWebPanel). It uses pin 10 for the sensor connection.

If it does not work for you, I will try to find some other examples.

/*
 Find and list DS18B20 addresses to web page
 
 
 created 20 October 2013
 by Bjarne B. Christensen
 
 This code is in the public domain.
 */

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
#include <OneWire.h>

// Listen on default port 5555, the webserver on the Yun
// will forward there all the HTTP requests for us.
YunServer server;
String startString;
long hits = 0;

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)

void setup() {
   Serial.begin(9600);

   // Bridge startup
   pinMode(13,OUTPUT);
   digitalWrite(13, LOW);
   Bridge.begin();
   digitalWrite(13, HIGH);

   // Listen for incoming connection only from localhost
   // (no one from the external network could connect)
   server.listenOnLocalhost();
   server.begin();

   // get the time that this sketch started:
   Process startTime;
   startTime.runShellCommand("date");
   while(startTime.available()) {
      char c = startTime.read();
      startString += c;
   }
}

void loop() {
   byte i;
   byte present = 0;
   byte data[12];
   byte addr[8];
   float celsius, fahrenheit;

   // Get clients coming from server
   YunClient client = server.accept();

   // There is a new client?
   if (client) {
      // read the command
      String command = client.readString();
      command.trim();        //kill whitespace
      Serial.println(command);
      // is "temperature" command?
      if (command == "temperature") {

      while (ds.search(addr)) {
         Serial.print("Found address: ");
         for(i = 0; i < 8; i++) {
            if(addr[i] < 16) Serial.print("0");
            Serial.print(addr[i], HEX);
            Serial.print(" ");
         }

         if (OneWire::crc8(addr, 7) != addr[7]) {
            Serial.println("CRC is not valid!");
            return;
         }

         if (addr[0] != 0x28) {
            return;
         }
         Serial.println();
         Serial.println("Valid Sensor ID");

         client.print("
Sensor Address: ");
         for(i = 0; i < 8; i++) {
         if(addr[i] < 16) client.print("0");
            client.print(addr[i], HEX);
            client.print(" ");
         }
      }
      ds.reset_search();
      delay(250);
      client.print("
Hits so far: ");
      client.print(hits);
      // Close connection and free resources.
      client.stop();
      hits++;
      }
   }
   delay(50); // Poll every 50ms
}

Hi Bjarne, that worked perfectly, thank you so much!

Cheers, Adrian

You are welcome !

Hi Bjarne, although that code is working well, I find that it cannot sustain the polling of the sensors for even a day. I’m just wondering if you have had any problems around this?

I was thinking it maybe had a memory leak, so I installed these libraries o check that:

#include <MemoryFree.h>
#include <pgmStrToRAM.h>

It reports no appreciable memory loss (around 1083), but after about 4000 iterations it just stops.

Any ideas?

Tks, AB

Hi Adrian,

What sketch are you running, the Address Search example I posted? I have never run that for more than probably 10 minutes at a time, but my main sketch (using the same library) has run for about 5 days. I has never stopped on it's own, the reason it is only 5 days is, that I test different things, so that creates a restart.

Any clue to where it 'hangs' or crashes ? How close are you to the memory limits when loading the sketch? Are you maybe losing WiFi connection, a problem several people seem to have ?

cheers, Bjarne

Hi Bjarne, no clue to where it hangs, is there perhaps a way to determine that in a sketch? I have modified your code somewhat, so i could have introduced the problem.

I guess it could be losing wifi, didn't think about that. Also, I'm powering it from my laptop which turns off USB power when I close it. If I leave it powered on after it stops, then power it down, when I power it back up, it does not automatically restart, which is weird. If I then unplug and plug it back in, it restarts ok.

Regards, Adrian

Hi Adrian,

One thing I do is to blink the LED in the loop() at 1 sec off/1 sec on, that way I have confirmation that it is executing the loop().

I don't mind sharing my main sketch, but I am not sure how useful it would be for you, as I do things quite a bit different there. I have moved as much processing and code to the Linino side as I could easily do, as I kept running up against the memory limit on the Arduino side. For example, I don't use YunServer and YunClient, but rather I store the sensor data in a csv file on the SD card. I then have a php script called from the web side to serve the data to the browser. So I have installed additional packages on the Linino side for php and also ssmtp for email.

Hi Bjarne, the LED blink is a good way to determine if the sketch is still running, I’ll try that, thanks.

No need to send anymore scripts as I am even less tied to the Yun in that I have it poke the sensor data to a PHP page on my remote server. I’m still evaluating other units, particularly those using node.js

Regards, AB

Hi Bjarne, so I tried your idea of the LED blink for every loop of the program code, and the problem did turn out to be the code itself, it just stops.

Then I went back and got your original code and only modified it by adding the blink output so that I could visually check it. I extended the timing a bit after the reset so that it slowed it down. It made it to about 250 iterations then died, so at this point I'm not sure if my YUN is defective or there's something happening in that code that causes the problem - any ideas?

Regards, Adrian

Hi Adrian,

As I mentioned, I only run the code you have for a few minutes to collect the addresses of my sensors, so I can’t say how long it would run on my Yun. My main sketch have run for 4 or 5 days at a time, so I have much more confidence in that. I stripped out a bit of non-exxential code in my sketch and I will run it overnight, and if it runs as I expect, I will post it for you to try.

Bjarne

Hi Adrian, here is the sketch I ran overnight, it is my main sketch that I stripped some non-essential code out of. It reads the sensors every five minutes and stores the results in a csv file on the SD in the directory /mnt/sd/data/greenhouse. It starts a new file every day at midnight. I have never had this sketch stop by itself. I think that part of the problem you are having is that the search function in the library may not be as robust as you would like, but since I never use it for anything other than discovering the addresses of my sensors, it has never been a problem for me.

TestDS18B20.h

byte boardAddress[8] = {0x28, 0x15, 0xA2, 0x04, 0x05, 0x00, 0x00, 0x25};
byte outdoorAddress[8] = {0x28, 0x31, 0x43, 0x06, 0x05, 0x00, 0x00, 0x5F};
byte indoorAddress[8] = {0x28, 0x8D, 0xAC, 0x05, 0x05, 0x00, 0x00, 0x18};

TestDS18B20.ino

/*
  Controls the Green House
  
  This version samples the temperature every five minutes and stores
  the result on the SD card.
  
  The data can be retrieved from the SD card via the web interface.
  
  created 26 October 2013
  by Bjarne B. Christensen
  
  This code is in the public domain
  
*/

#include <Bridge.h>
#include <FileIO.h>
#include <Process.h>
#include <OneWire.h>
#include "SensorAddresses.h"

Process time;
String minuteString;
String timeString;
String dateString;
String nowMinuteString = "";
float boardTemperature;
float outdoorTemperature;
float indoorTemperature;
char charBuf[40];
int nextMinute = 0;
int minute;
boolean armEmail = true;
int tries;
int test = 0;
int led = 13;   // LED on pin 13
String ledTest;
byte previous_state = 0;

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)

void setup() {
   pinMode(led, OUTPUT);
   Serial.begin(9600);

   // Bridge startup
   pinMode(13,OUTPUT);
   digitalWrite(13, LOW);
   Bridge.begin();
   digitalWrite(13, HIGH);
 
   delay(60000);  // to let Linino finish booting
   getTime();

   nextMinute = (minute - minute%5) + 5;
   if(nextMinute > 59) nextMinute -= 60;

   FileSystem.begin();
}

void loop() {
   getTime();
   
   ledTest = timeString.substring(7);
   if((ledTest == "0") || (ledTest == "2") || (ledTest == "4") || (ledTest == "6") || (ledTest == "8")) {
      digitalWrite(led, 1);
   } else {
      digitalWrite(led, 0);
   }
   
   if(timeString.substring(0,5) == "00:00") {
      if(armEmail) {
         armEmail = false;
         String file = dateString;
         file += ".csv";
         String message = "Time,Voltage,Board,Outside,Inside,";
         message += dateString;
         logEntry(file, message);
      }
   } else {
      armEmail = true;
   }
   
   if(minute == nextMinute) {
      nextMinute = minute + 5;
      if(nextMinute > 59) nextMinute -= 60;
      checkTemperatures();
   }

   delay(50); // Poll every 50ms
}

void checkTemperatures()
{
   String message = timeString.substring(0,5);
   message += ",0.0,";
   boardTemperature = DS18B20read(boardAddress);
   message += boardTemperature;
   message += ",";
   outdoorTemperature = DS18B20read(outdoorAddress);
   message += outdoorTemperature;
   message += ",";
   indoorTemperature = DS18B20read(indoorAddress);
   message += indoorTemperature;
   message += ",50";

   String file = dateString;
   file += ".csv";
   logEntry(file, message);
}

float DS18B20read(byte *addr)
{
	byte i;
	byte data[12];
	float celsius;

	if (ds.crc8(addr, 7) != addr[7]) {
		Serial.println("CRC is not valid!");
		return 100;  // flag - recognizable 'wrong' value
	}

	if (addr[0] != 0x28) {
		return 95;  // flag - recognizable 'wrong' value
	}

	ds.reset();
	ds.select(addr);
	ds.write(0x44, 1);        // start conversion, with parasite power on at the end

	//delay(1000);     // maybe 750ms is enough, maybe not
	delay(1500);     // seems like some of my sensors don't meet the time spec at low temps

	ds.reset();
	ds.select(addr);    
	ds.write(0xBE);         // Read Scratchpad

	for ( i = 0; i < 9; i++) {           // we need 9 bytes
		data[i] = ds.read();
	}

	int16_t raw = (data[1] << 8) | data[0];
	byte cfg = (data[4] & 0x60);
	if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
	else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
	else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
	
	celsius = (float)raw / 16.0;
	return celsius;
}

void getTime() {
   Process time;
   String tempString;
   boolean valid = false;
   
   tries = 0;
   while(!valid) {
     tries++;
      // get the time from the server:
      time.runShellCommand("date +\"%Y%m%d %T\"");
      //while(time.running());  
      tempString = "";
      while(time.available()) {
         char c = time.read();
         if(c != '\n')
            tempString += c;
      }
      dateString = tempString.substring(0, 4) + "-" + tempString.substring(4, 6) + "-" + tempString.substring(6,8);
      if(dateString != "2013-10-20") valid = true;
  }
   timeString = tempString.substring(9);
   minuteString = tempString.substring(12,14);

   minuteString.toCharArray(charBuf, 30);
   minute = atoi(charBuf);
}

void logEntry(String file, String message)
{
   String fileName;
   
   fileName = "/mnt/sd/data/greenhouse/";
   fileName += file;
   fileName.toCharArray(charBuf, 40);
   File dataFile = FileSystem.open(charBuf, FILE_APPEND);
   
   dataFile.println(message);
   dataFile.close();
}

The 60 sec delay in setup() is only needed when starting from power-up, so can be commented out for testing with only uploading.

Bjarne