DuinOS + Arduino 1.03 + DS18B20

Hello.

In my small project I'm using DuinOS(downloaded here GitHub - carlosdelfino/DuinOS: Este repositório está sendo atualizado com menos frequência, Atualizações no Link: http://github.com/DuinOS/DuinOS), Arduino(Uno) v.1.03 and DS18B20. And here is the place, where problems have come from... I've created a separated task for the temperature reading and I've copied the code from the OneWire examples into the task and modified it a bit to use a lcd -screen, instead of Serial monitor. After that, I've built the app and run it... So, getting to the point, the app gets stuck here(or hung, whatever you'd like more =) ):

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

lcd.print("WE ARE HERE");           //THIS LINE WILL NEVER BE REACHED

After all, Arduino get stuck too. In other words, the data cannot be read or written into the device or from the device.

Does anybody know, how could this problem to be solved?

Thank you beforehand for your answers.

We need the full code.

Thank you for your answer.

Here is the code of the small project:

#include <LiquidCrystal.h>
#include <OneWire.h>

#include <string.h>
#include <stdio.h>

#define LENGTH 32

LiquidCrystal lcd(8, 11, 9, 4, 5, 6, 7);
OneWire ds(4);

int inputBtn = 0;
char buffer[LENGTH];
enum States{Stop = 0, Start} states;

taskLoop(ReadButton)
{
  checkBtn();  
  delay(50);
}

taskLoop(ReadTemperature)
{
  if(states == Start)
  {
     byte i;
	byte present = 0;
   byte type_s;
   byte data[12];
   byte addr[8];
   float celsius;
  
  if ( !ds.search(addr)) {
    lcd.clear();
	 lcd.print("No more addresses");
    ds.reset_search();
    delay(250);
    return;
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
		lcd.clear();
      lcd.print("CRC is not valid!");
      return;
  }
 
  // the first ROM byte indicates which chip
  //we don't need it. Since the device's type_s = 0
  switch (addr[0]) {
    case 0x10:
     //old DS1820
      type_s = 1;
      break;
    case 0x28:
      //Chip = DS18B20;
      type_s = 0;
      break;
    case 0x22:
      //Chip = DS1822;
      type_s = 0;
      break;
    default:
      return;
  } 

  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
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
  }        
//The app will never pass here

  // convert the data to actual temperature

  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  ToString(celsius);
  lcd.clear();
  lcd.print(buffer);
  }
  delay(100);
}

void ToString(float num)
{
  memset(buffer, 0, LENGTH);
  sprintf(buffer, "%.2f", num);
}

void checkBtn()
{
  inputBtn = analogRead(0);
  if(inputBtn >= 710 && inputBtn < 900) 
  {
    states = Start;
  }  
  else if(inputBtn >= 470 && inputBtn < 700)
  {
    states = Stop;
    lcd.clear();
    lcd.print("Stopped");
  }
}

void setup()
{
  lcd.begin(16, 2);
  lcd.home();
  lcd.print("Greetings!");
  createTaskLoop(ReadButton, NORMAL_PRIORITY);
  createTaskLoop(ReadTemperature, NORMAL_PRIORITY);
}

void loop()
{
 //TO DO: add some code
}

Was this an example, or did you make this yourself?

Does your code know to go to,
createTaskLoop(ReadButton, NORMAL_PRIORITY);
createTaskLoop(ReadTemperature, NORMAL_PRIORITY);

and not,
TaskLoop(ReadButton, NORMAL_PRIORITY);
TaskLoop(ReadTemperature, NORMAL_PRIORITY);

What is the code doing?

sprintf(buffer, "%.2f", num);

AFAIK sprintf can't do floating point conversions so this probably puts a null in the buffer and you end up displaying nothing.
So, what exactly is printed on the Serial monitor?

Pete

HazardsMind:
Was this an example, or did you make this yourself?

Does your code know to go to,
createTaskLoop(ReadButton, NORMAL_PRIORITY);
createTaskLoop(ReadTemperature, NORMAL_PRIORITY);

and not,
TaskLoop(ReadButton, NORMAL_PRIORITY);
TaskLoop(ReadTemperature, NORMAL_PRIORITY);

What is the code doing?

Basically it's the same code as was behind the link I published first. Arduino is waiting for the user input. Then the reading starting. So, the app just read the sensor's value, convert it to the temperature and print it to the LCD -screen. Also, there is a stop button. Thus user can stop reading whenever she wants.
About createTaskLoop(...) - yes, you are right, probably I didn't copy it from the project file well. It was a ready example, which is shipped with a current version of the OneWire -library. In the original example there is no any tasks either lcd-screens or buttons. Only a serial monitor. But, if you will try to compile it and run, you'll face the same problem.

p.s. I'm sorry for the bad explanation of the problem.

el_supremo:

sprintf(buffer, "%.2f", num);

AFAIK sprintf can't do floating point conversions so this probably puts a null in the buffer and you end up displaying nothing.
So, what exactly is printed on the Serial monitor?

Pete

Sorry, for the bad explanation. Serial monitor doesn't print anything. I changed the example and replaced the Serial.print with lcd.print. Basically it does the same work - prints the data out. But I've tried both serial and lcd. Neither of them will print anything after the sensor reading was done.
But sprintf is a common C function which was used for decades and everything worked before, even with a float -type.

But sprintf is a common C function which was used for decades and everything worked before, even with a float -type.

If you say so, but try this sketch.

void setup(void)
{
  Serial.begin(9600);
  char oline[32];
  sprintf(oline,"float '%6.2f'",6.231);
  Serial.println(oline);
}

void loop(void){}

Pete

el_supremo:

But sprintf is a common C function which was used for decades and everything worked before, even with a float -type.

If you say so, but try this sketch.

void setup(void)

{
 Serial.begin(9600);
 char oline[32];
 sprintf(oline,"float '%6.2f'",6.231);
 Serial.println(oline);
}

void loop(void){}




Pete

OK, I admit, may be Arduino handle this function in a different way. Also, I googled recently a topic about problem you mentioned. But the problem is not there at all. Arduino doesn't even pass there. It will get stuck or hung right after the data reading.

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

  • }*
    //Program will not pass here.
    So this code:
    unsigned int raw = (data[1] << 8) | data[0];
  • if (type_s) { ......................*
    will not be executed. So I know the exact place where the app gets stuck. And I suspect the data reading.

So I know the exact place where the app gets stuck

It doesn't print anything at that point so how can you know that it gets stuck there?
And it would help if you post the code that you are talking about, all of it.
BTW. It would be better if you use Serial.println for debugging messages rather than LCD.print just to be sure that there's no problem with the LCD.

Pete

Thank you for your answer.
ABout printing, Serial Monitor doesn't print any information after the attempt to read bytes from the device.
Here is the code I'm using now for testing(It's not that good as I want to, but for the testing purposes it works well):

#include <LiquidCrystal.h>
#include <OneWire.h>

#include <string.h>
#include <stdio.h>

#define LENGTH 32

LiquidCrystal lcd(8, 11, 9, 4, 5, 6, 7);
OneWire ds(4);

int inputBtn = 0;
char buffer[LENGTH];
enum States{Stop = 0, Start} states;

taskLoop(ReadButton)
{
  checkBtn();  
  delay(50);
}

taskLoop(ReadTemperature)
{
  if(states == Start)
  {
     byte i;
	byte present = 0;
   byte type_s;
   byte data[12];
   byte addr[8];
   float celsius;
  
  if ( !ds.search(addr)) {
    lcd.clear();
	 lcd.print("No more addresses");
    ds.reset_search();
    delay(250);
    return;
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
		lcd.clear();
      lcd.print("CRC is not valid!");
      return;
  }
 
  // the first ROM byte indicates which chip
  //we don't need it. Since the device's type_s = 0
  switch (addr[0]) {
    case 0x10:
     //old DS1820
      type_s = 1;
      break;
    case 0x28:
      //Chip = DS18B20;
      type_s = 0;
      break;
    case 0x22:
      //Chip = DS1822;
      type_s = 0;
      break;
    default:
      return;
  } 

  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
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
  }        
//The app will never pass here

  // convert the data to actual temperature

  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  ToString(celsius);
  lcd.clear();
  lcd.print(buffer);
  }
  delay(100);
}

void ToString(float num)
{
  memset(buffer, 0, LENGTH);
  sprintf(buffer, "%.2f", num);
}

void checkBtn()
{
  inputBtn = analogRead(0);
  if(inputBtn >= 710 && inputBtn < 900) 
  {
    states = Start;
  }  
  else if(inputBtn >= 470 && inputBtn < 700)
  {
    states = Stop;
    lcd.clear();
    lcd.print("Stopped");
  }
}

void setup()
{
  lcd.begin(16, 2);
  lcd.home();
  lcd.print("Greetings!");
  createTaskLoop(ReadButton, NORMAL_PRIORITY);
  createTaskLoop(ReadTemperature, NORMAL_PRIORITY);
}

void loop()
{
 //TO DO: add some code
}

How could I know the Arduino gets stuck there? I put the lcd.print("TEST"); delay(5000); before bytes reading and lcd.print("ABC"); delay(5000); after reading. So, the first one will be printed. But the second one will not be printed, even after 5 seconds of waiting. Also I've tried to do it without delays. Result is the same. I've tried to do it with a serial monitor - same result as before.

I really appreciate, if somebody will show me the working code for the same configuration: Arduino Uno 1.03 + DS18B20 + DuinOS v. 0.4 alpha.

I know, Arduino all alone works perfectly with onewire, but I need a bit more for my small project.

I know, Arduino all alone works perfectly with onewire

Have you tried using DuinOS with only the DS18B20? Let's make sure that DuinOS and DS18B20 will even work together when there's nothing else that might get in the way.

Pete

I didn't, but let's say, this one: DuinOS + Arduino 0023 + DS18B20 will work.

let's say, this one: DuinOS + Arduino 0023 + DS18B20 will work

"will" work or "does" work?

You need to do some tests to eliminate potential sources of problems/conflicts. So, can you get DuinOS + Arduino 1.03 to work with only the DS18B20?

Pete

el_supremo:

let's say, this one: DuinOS + Arduino 0023 + DS18B20 will work

"will" work or "does" work?

You need to do some tests to eliminate potential sources of problems/conflicts. So, can you get DuinOS + Arduino 1.03 to work with only the DS18B20?

Pete

I meant it does work.

I can't get work DuinOS + Arduino 1.03 with only DS18B20. I've already tried to treat it as parasite device with all resets included according to this one http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf. I tried to change resistance - nothing.

"DuinOS + Arduino 0023 + DS18B20" works but "DuinOS + Arduino 1.03 + DS18B20" doesn't.
Is DuinOS the same version in both cases? If it is, then the change to Arduino 1.03 would appear to be the culprit. But if the first DuinOS is 0.3 and the second is 0.4 it is more likely that DuinOS 0.4 has a bug and you'd be best to stick with 0.3.

Pete