Dallas sensors puzzle - sensors.begin()



  • Sorry for the long post, but hoping somebody has come across this problem and figured it out.
    Have been trying to figure out why a standalone sketch interrogating a chain of DS18B20s and still working away happily to this day, throws wobblies when incorporated in a new sketch for a boiler monitor.

    • 1 A reduced address table version of the original standalone sketch reads both devices no problem, but problems arise when modified to look at two additional ADC inputs.

    • 2 The boiler sketch used exactly the same libraries (DallasTemperature + OneWire + MySensors+T2WhisperNode) as previously, updated all libraries since and still get the same issues persist every time.

    • 3 Compile errors - Threw a wobbly over functions written to follow after void(loop). Eventually solved by moving them before void(setup) and it compiled fine, (subsequently found simply calling the funtion from there also solved the compile issue) but the pro-mini locked up on restart never reaching void(loop).
      After some poking around, found if the command "sensors.begin()" was commented out, no lockups, no compilation problems irrespective of where functions were located, but of course the temperatures could not be obtained.

    For completeness, the original sketch was to fetch start and finish times from an RTC, but it was the first thing discarded in trying to find a solution, hence the slightly more convoluted method and inaccurate format. The intent had been to use unixtime to verify start and finish times such that part minutes continued to accumulate until reconciled.
    Hopefully some of you experts can shed some light on this before I lose all my hair in time for Christmas...

    #include <T2WhisperNode.h>
    
    
    // Enable debug prints to serial monitor
    //#define MY_DEBUG //Comment out once all working saving memory
    // Enable and select radio type attached
    
    #define MY_RADIO_RFM69
    #define MY_RFM69_FREQUENCY RFM69_433MHZ  // Define for frequency setting. Needed if you're radio module isn't 868Mhz (868Mhz is default in lib)
    #define MY_RFM69_NETWORKID 101  // Default is 100 in lib. Uncomment it and set your preferred network id if needed
    #define MY_NODE_ID 8  //Manually set the node ID here. Comment out to auto assign
    
    #include <SPI.h>
    #include <MySensors.h>
    /*#include <DallasTemperature.h>
    #include <OneWire.h>
    #define COMPARE_TEMP 1 // Send temperature only if changed?
    #define ERASE_HASH // Clear EEPROM, if no 1w-device is present?
    #define ONE_WIRE_BUS 16 // Pin where dallas sensor is connected 
    #define MAX_ATTACHED_DS18B20 2*/
    #define SN "Node8BoilerT3vWN"
    #define SV "2"//counter error rectified, power failure added
    
    #define FIRST_CHILD_ID 1
    #define THIRD_CHILD_ID 3
    #define FOURTH_CHILD_ID 4
    #define FIFTH_CHILD_ID 5
    #define SIXTH_CHILD_ID 6
    #define TENTH_CHILD_ID 10
    #define ELEVENTH_CHILD_ID 11
    
    #define BatteryOn 14
    #define VBAT A6
    #define VIN A7
    #define Tpower 17
    #define Volts A1
    #define flasher 6
    #define flasher2 9
    bool boiler=true;
    bool powercut=true;
    boolean metric = true;
    bool psu=true;
    bool prevboil=false;
    bool prevpower=false;
    bool prevfail=false;
    unsigned long Powercuts=0L;
    unsigned long Powerstart=0L;
    unsigned long Boilertrack=401L;// Verify last measure before programming
    int divider=600;
    int counter=6;
    int boilercycle=60;
    int idling=0;
    int puzzling=0;
    /*
    uint8_t DS_First_Child_ID = 8; //First Child-ID to be used by Dallas Bus; set this to be higher than other Child-ID's who need EEPROM storage to avoid conflicts
    OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature.
    //float lastTemperature[MAX_ATTACHED_DS18B20];///?????????????????
    */
    // Change to V_LIGHT if you use S_LIGHT in presentation below
    MyMessage msg1(FIRST_CHILD_ID, V_STATUS);//Switched to version 7 kWh
    //MyMessage msg2(SECOND_CHILD_ID, V_VOLUME);
    MyMessage msg3(THIRD_CHILD_ID, V_VOLTAGE);
    MyMessage msg4(FOURTH_CHILD_ID, V_VOLTAGE);
    MyMessage msg5(FIFTH_CHILD_ID, V_STATUS);
    MyMessage msg6(SIXTH_CHILD_ID, V_KWH);
    MyMessage msg10(TENTH_CHILD_ID, V_KWH);
    MyMessage msg11(ELEVENTH_CHILD_ID,V_STATUS);
    // Initialize temperature message
    MyMessage DallasMsg(0, V_TEMP);
    
    void presentation(){
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo(SN, SV);
      // Register binary input sensor to sensor_node (they will be created as child devices)
      // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage.
      // If S_LIGHT is used, remember to update variable type you send in. See "msg" above.
      present(FIRST_CHILD_ID, S_HEATER);
      present(THIRD_CHILD_ID, S_MULTIMETER);
      present(FOURTH_CHILD_ID, S_MULTIMETER);
      present(FIFTH_CHILD_ID, S_HEATER);
      present(SIXTH_CHILD_ID, S_POWER);
      present(TENTH_CHILD_ID, S_POWER);
      present(ELEVENTH_CHILD_ID, S_HEATER);}
    /*  for (int i = 0; i < MAX_ATTACHED_DS18B20; i++) {
        present(DS_First_Child_ID + i, S_TEMP);
      }8?
      }/*
    #ifdef PRINT_ARRAY
    DeviceAddress dallasAddresses[8];
    #else
    DeviceAddress dallasAddresses[] = {
      {0x28, 0xD7, 0x26, 0xA0, 0x0B, 0x00, 0x00, 0x53},
      {0x28, 0x7F, 0x0C, 0xA2, 0x0B, 0x00, 0x00, 0xEC},
    };
    #endif
    //1st is Boiler Return 2nd is Output
    int  resolution = 9;
    int  conversionTime = 750;
    */
    
    void before() {
      pinMode(Tpower, OUTPUT);
      digitalWrite(Tpower,HIGH);
      sleep (1000);
    }
    
    void setup ()  {
       pinMode(BatteryOn, OUTPUT);//WN battery sample activation pin
       pinMode(VBAT, INPUT);//WN ADC for battery read 
       pinMode(VIN, INPUT);//WN Mains PSU ADC
       pinMode(Volts, INPUT);//Boiler relay voltage divider
       pinMode(flasher,OUTPUT);
       analogReference(INTERNAL);//All ADC reads reference 1.1v
       sleep(100);//Allow things to settle
     }
    
    void loop(){ 
      //Loop cycles once for any change to two logicals, psu and boiler, otherwise internal cycles
    if(analogRead(VIN)>=divider){//flash only if not on batteries
      VOFF();}
    //Test logic
        if(analogRead(Volts)<=divider){//Boiler - True if low or outage, False if standby.
          boiler=true;}
        else{
          boiler=false;}
          wait(20);
        if(analogRead(VIN)>=divider){//PSU - True if powered, False if offline
          psu=true;}
        else{
          psu=false;}
        if(boiler&&!psu){//True if outage or boiler running but psu offline
          powercut=true;}
        else{
         powercut=false;}
      sleep(10);//NOTE - INSERT CHANGE CONDITION HERE
       send(msg1.set(boiler));//Send current Boiler
        sleep (20);
       send(msg5.set(powercut));//Send Powercut suspected
       sleep(20);
       send(msg11.set(!psu));//Send current PSU as inversion to indicate power failure
       sleep(20);
      
    //INCREMENT TO TAKE VOLTAGE READINGS EVERY 6 BURNER CYCLES
       if (boiler&&psu){//Power On Boiler running
       ++counter;
       if (counter>=6){
        ReadSupplies();
        counter=0;}}
     
    //BOILER RUN CYCLE PSU WORKING  
    wait (10);
        while(boiler&&psu){//ADC tests in break below
        sleep(1000);//NOTE - NOT ACCURATE SECONDS DUE TO ADC TESTS
        ++boilercycle;
        if(analogRead(Volts)>=divider){//Boiler gone standby
          break;}
          sleep(20);
        if(analogRead(VIN)<=divider){//PSU failed
          break;}
          sleep(20);
    /*      if(boilercycle=59){
          sensors.requestTemperatures();} //will not block current thread
          //report every minute*/
        if (boilercycle>=60){
           ++Boilertrack;
           send(msg10.set(Boilertrack));//Update kWh run
           VON();
    //       MANIFOLDS();//Check both temperatures
            boilercycle=0;} }//Reset 1 minute cycle
    
    //PSU AND BOILER POWER FAILURE. NOTE - can also occur if PSU disconnected and boiler runs
       Powerstart=Powercuts;
       while (boiler&&!psu){
          sleep(1000);
          Powercuts++;
          if(analogRead(Volts)>=divider){
          break;}
          sleep(20);
          if(analogRead(VIN)>=divider){
          break;}
       }
       
    //UPDATE READING FOR POWERCUTS ALLIED TO ABOVE
       if (Powercuts>Powerstart){
       send(msg6.set(Powercuts));}
       
    //PSU AND BOILER ON STANDBY
    wait (10);   
    idling=0;
       while (!boiler&&psu){//Power On Boiler Off
        sleep(1000);
        idling++;
        if(analogRead(Volts)<=divider){
          break;
        sleep(20);}
        if(analogRead(VIN)<=divider){
          break;}
    /*    if(idling=299){
          sensors.requestTemperatures();} //will not block current thread*/
          //report every 5 minutes
        if(idling>300){
           VON();
    //       MANIFOLDS();
           boilercycle=0;}
           idling=0; }
    
    //BOILER THEORETICALLY ON STANDBY BUT NO PSU, HENCE WTF
        while(!boiler&&!psu){
          sleep(1000);
          if(analogRead(Volts)<=divider){
          break;
        sleep(20);}
        if(analogRead(VIN)>=divider){
          break;}
          puzzling++;
          if(puzzling>=300){
            puzzling=0;}  
          }
    
       sleep(1000);
    } // end of loop
    /*
    void MANIFOLDS(){
      // Read temperatures and send them to controller
      for (int i = 0; i < MAX_ATTACHED_DS18B20; i++) {
        // Fetch and round temperature to one decimal; original method uses "sensors.getTempCByIndex(i)"
        float temperature = static_cast<float>(static_cast<int>((metric ? sensors.getTempC(dallasAddresses[i]) : sensors.getTempF(dallasAddresses[i])) * 10.)) / 10.;
          if (temperature != -127.00 && temperature != 85.00) {
          // Send in the new temperature
          send(DallasMsg.setSensor(i + DS_First_Child_ID).set(temperature, 1));
          wait(100);}
      }
    }
    */
    
    void VON(){
      digitalWrite(flasher,HIGH);
      sleep (6);
      digitalWrite(flasher,LOW); 
    }
    
    void VOFF(){
      for(int a=0;a<=2;a++){
      digitalWrite(flasher,HIGH);
      sleep (6);
      digitalWrite(flasher,LOW); 
      sleep (6);}
    }
    
    void ReadSupplies(){
      digitalWrite(BatteryOn, HIGH);
      int voltread = analogRead(VBAT);
      float voltage = (7.272 * voltread) / 1024;
      sleep(5);
      digitalWrite(BatteryOn, LOW);
      int supplyread = analogRead(VIN);
      float USBvoltage = (7.272 * supplyread) / 1024;
      sleep(5);
      send(msg3.set(voltage,2));
      wait(100);
      send(msg4.set(USBvoltage,2));
      wait(100);
    }
    


  • @zboblamont
    Although I didn't completely analyse your sketsch I remember from some time ago that I ran into problems once I moved the one-wire- pin from 3 to another pin. No idea why, and never actually took the time to troubleshoot this, but when I brought it back to pin 3 all my problems disappeared with the dallas sensors.

    Hope it helps.

    BR,

    Boozz



  • @boozz Cheers, D3 is currently unused as yet, so worth a try in the morning even if it makes no sense that it's a physical rather than a software issue.
    Tried finding example sketches where folks had used DS18B20 as part of a multipurpose Node for clues, but could only find dedicated sketches. Fairly sure it is out there, just haven't found one yet.
    As explained in the OP, had reprogammed the Node with the original internal temp sensor sketch cut down from 12 to 2 addresses, same pin 16 used, compiled and worked no problem so it shouldn't be a library problem.
    It's only since expanding the sketch to not make it dedicated to a single task where the trouble began.



  • How is your memory usage?



  • @electrik 40% program storage space, 38% dynamic memory.


  • Hardware Contributor

    @zboblamont
    maybe this is some blocking code, I've no clue I've not tried replicating your issue as I'm busy but I have a non updated/optimized sketch, quite old, where I used one ds28b20 in a non blocking way if I remember.

    https://github.com/scalz/MySensors-HW/blob/development/RollerShutterNode/FW/MyRollershutter/MyRollershutter.ino#L386

    you might just need to use initDS18x20() and temperatureProcess(). I don't think I changed the onewire lib, I'll check later if I remember 🙂

    I hope that will help



  • @scalz That may well help even if I'll struggle to understand it. At least your setup combines similar basic principles to my objective.
    Since the OP, have nailed "sensors.begin()" which causes problems as a Dallas library call, and as your sketch does not employ that library, perhaps a glimmer of a solution....
    Many thanks for that.
    Cheers...


Log in to reply
 

Suggested Topics

4
Online

9.5k
Users

10.1k
Topics

105.1k
Posts