element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Internet of Things
  • Technologies
  • More
Internet of Things
Blog Old meets new, the 1-Wire Weather Station on the SPARK Core. (part 5)
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Internet of Things to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: gpolder
  • Date Created: 7 Jan 2015 9:38 PM Date Created
  • Views 3296 views
  • Likes 7 likes
  • Comments 12 comments
  • weather_station
  • 1-wire
  • 1_wire_bus
  • spark_core
  • internet-of-things
Related
Recommended

Old meets new, the 1-Wire Weather Station on the SPARK Core. (part 5)

gpolder
gpolder
7 Jan 2015

In my previous blog posts I mainly focused on the IoT aspects of the project. In Old meets new, the 1-Wire Weather Station on the SPARK Core. (part 2) I showed a scan of the 1-Wire bus, which showed the devices in the 1-Wire Weather Station. In the last one Old meets new, the 1-Wire Weather Station on the SPARK Core. (part 4) I showed how two extra 1-Wire temperature sensors ar read and published in the cloud. In Old meets new, the 1-Wire Weather Station on the SPARK Core. (part 1) I very briefly introduced you to the Weather Station. It's now time to go into more detail into the hardware and the software to read out the weather data.

The description of the hardware is based on a document written by Dan Awtrey from Dallas Semiconductor.(http://www.midondesign.com/Documents/1wire_weather_stn.PDF)

 

1-Wire Weather Station

A diagram of the basic 1-Wire weather station is shown below:

image

 

Eight compass points are directly measured with eight reed switches actuated by a magnet attached to the weather vane axle. Whenever the magnet is between two adjacent reeds both switches close. This supplies an additional eight directions, for a total of sixteen compass points. Note that the bus master can only read wind direction when the DS2407 addressable switch is closed. Similarly, a magnet attached to the wind cups operates a reed switch connected to the DS2423 counter chip that keeps track of the total number of revolutions the cups make and provides the data to the bus master on demand. Ambient temperature is measured with a DS1820 Digital Thermometer. Below is the detailed schematic.

 

image

 

As you can see in the pictures, all 1-Wire devices are connected in parallel to the 1-Wire bus. By issuing a search command on the bus one can find the unique addresses of all these chips:

 

void findDevices() {
    uint8_t addr[12];
    int found = 0;
    int counter;
    while(one.search(addr)) {
        Serial.print("Found device: ");
        char *owID = new char[24];
        sprintf(owID, "%02x%02x%02x%02x%02x%02x%02x%02x",
            addr[0],  addr[1], addr[2] , addr[3] , addr[4] , addr[5], addr[6], addr[7]
        );
        sensors[found].id = owID;

        for(int i=0;i<8;i++)
        {
            sensors[found].rom[i] = addr[i];
        }

        sensors[found].updated = 0;
        Serial.print(owID);

        if (addr[0] == 0x22) { //ds1822 temp sensor
            getTempBytes(sensors[found].rom);
            sensors[found].value = getTemp('C',12);
            Serial.print(" Temperature: " + String(getTemp('C',12)));
            sensors[found].updated = millis();
        }
        if (addr[0] == 0x10) { //  DS1820 temp sensor
            getTempBytes(sensors[found].rom);
            sensors[found].value = getTemp('C',9);
            Serial.print(" Temperature: " + String(sensors[found].value));
            sensors[found].updated = millis();
        }
        if (addr[0] == 0x1D) { //ds2423 counter
            counter = readCounter(sensors[found].rom,2);
            uint32_t now = millis();
            sensors[found].value = ((counter - oldcounter) *1000/(now - timestamp) / 2.0) ;  // in m/s ????
            Serial.print(" Windspeed: " + String(sensors[found].value));
            sensors[found].updated = now;
            timestamp = now;
            oldcounter = counter;
        }
        if (addr[0] == 0x12) { //  DS2407 switch
            setSwitch(sensors[found].rom,dirswitch);
            sensors[found].value = dirswitch;
            Serial.print(" Wind Direction: " + String(winddir));
            sensors[found].updated = millis();
            dirswitch = !dirswitch;
        }
        Serial.println("");
        found++;
    }
    for (int j = found; j<NUM_SENSORS;j++){
        sensors[j].id = NULL;
    }
}

 

Each found device is put into an array of sensor structs:

 

class OWSensor {
    public:
        char *id ;
        uint8_t rom[8];
        float value ;
        int updated ;
};

 

The first 8 bit (1 byte or 2 Hex characters) of the unique device address identifies the type of 1-wire device. See the family code list for the types.

Based on the family code different routines are used for measuring the specific feature.

 

Temperature

Ambient temperature is measured with the DS1820. This self contained sensor measures temperature as the difference between two oscillators, one of which is temperature dependent. The sensor functions over a -55 to 125°C range and provides plus and minus 0.5°C uncorrected accuracy over 0 to +70 °C. Normally this sensor would be mounted in a separate properly ventilated housing in order to measure ambient temperature as closely as possible. However, the initial design called for a single housing to simplify installation, so the sensor was mounted on the weather station PCB. Since exposure to the sun can raise the inside of the housing as much as 20 degrees higher than ambient, this arrangement can lead to large errors in the reading for many applications. In order to obtain a more accurate measure of ambient temperature an additional DS1820 can be mounted in a suitable separate enclosure and added to the bus by plugging into the daisy-chain connector provided on the PCB. Two functions are used for reading the temperature, getTemp for reading the temperature in Fahrenheit or Celcius and getTempBytes for reading the raw value from the sensor. Temperature can be read in 0.0625 or 0.25 degrees precision, depending on the sensor type used. Here I'm using the DS1820 on the Weather Station PCB, and a DS1822 close to the Spark Core.

 

void getTempBytes(uint8_t *rom) {
    one.reset();
    one.select(rom);
    one.write(0x44);
    delay(500);
    one.reset();
    one.select(rom);
    one.write(0xBE);
    one.read_bytes(resp, 9);
}

float getTemp(char unit, int precision) {
    byte MSB = resp[1];
    byte LSB = resp[0];
    float celcius;


    float tempRead = ((MSB << 8) | LSB); //using two's compliment
    switch (precision) {
        case 12:
            celcius = tempRead * 0.0625;
            break;
        case 9:
            celcius = tempRead * 0.25;
            break;
    }


    if (unit == 'F') {
        return (celcius * 1.8) + 32;
    } else {
        return celcius;
    }
}

 

Wind direction

The wind direction sensor consists of eight magnetically actuated reed switches mounted radially on a PCB at 22.5 degree intervals. Each reed switch is connected between the data line and a DS2401 Silicon Serial number, which provides an identification number for each switch. A rectangular activating magnet polarized with a single pole facing the reed switch, is mounted in a rotor attached to the weather vane axle. The rotor is designed so that one layout can be used for both the wind speed and direction sensors. When used for wind direction, a single magnet is mounted in either one of the two holes located near the center. As the wind rotates the vane and attached rotor, the magnet closes the switch as it passes over the reed. When a reed is closed, it’s companion DS2401 is connected to the bus (if the DS2407 Addressable Switch is on) and the master can read its serial number. This unique serial number identifies the reed switch, and the compass point it represents. Notice that the bus master can only read wind direction information when the DS2407 addressable switch is closed. This is for isolation reasons, otherwise, communication would be disrupted each time a reed switch closed and the DS2401 associated with it signaled its presence on the line. Communication with the wind direction sensor therefore begins when the bus master turns on the DS2407 output, connecting one side of all the DS2401s to the 1-Wire bus ground line. The weather vane with its rotor and magnet will be activating (closing) at least one of the reed switches connecting the other side of that DS2401 to the data line so the bus master can read its serial number. In the code is defined which compass point each DS2401 identifies, it knows which direction the vane is pointing when a particular DS2401 is on the bus. The eight reed switches directly indicate eight compass points. However, the length of the magnet is such that whenever it is approximately half way between two adjacent reed switches both are closed. The bus master understands that this means the weather vane is midway between two compass points, so eight additional directions are inferred, for a total of sixteen compass points. Unfortunately this is currently not implemented in the software.

The DS2407 is switched on and of in an alternating way by the find devices routine. When it is on the DS2401 which are found (maximal 2) are added to the sensor array, as can be seen in the code above.

 

void setSwitch(uint8_t *rom, bool on)
{
  one.reset();
  one.select(rom);


  one.write(0x55);
  one.write(0x07);
  one.write(0x00);
  if (on) {
    one.write(0x1F); // 1F direction on, 5F direction off
  } else {
    one.write(0x5F); // 1F direction on, 5F direction off
  }
  one.write(0xFF);
  one.write(0xFF);


  one.read_bytes(resp, 6);
  one.reset();
}

 

Wind Speed

Similarly, two magnets mounted on a second rotor attached to the wind cups axle operate a reed switch connected to the DS2423 counter chip which provides a unique identification for this sensor with its 1-Wire serial number. One magnet is mounted in each of the two outermost holes of the rotor. This provides two counts per revolution which improves response at low wind speeds. It also provides rotational balance to the rotor, which becomes important with increasing wind speed, as the rotor can reach 2400 rpm in 160 km/h winds. The DS2423 keeps track of the total number of revolutions the wind cups make and provides the data to the bus master on demand. The chip contains two 232 bit counters and can be powered for ten years with a small Lithium battery, however, here power for the counter chip comes from CR1 and C1 (Figure 1 again) which form a half wave rectifier that “steals” power from the data line. The DS2423 can only be reset to zero when this “parasite power” is lost. Wind speed is calculated by the bus master taking the difference between two counts of the counter used. One count generated before and the other after a clocked interval. The output is currently given in rpm. This later needs to be converted to m/s or km/h.

 

uint32_t readCounter(uint8_t *rom, uint8_t counter)
{
  uint8_t myTA1;

  one.reset();
  one.select(rom);
  one.write(0xA5);

  if (counter == 1) {
    myTA1 = 0xC0;
  }
  else if (counter == 2) {
    myTA1 = 0xE0;
  }

  one.write(myTA1);
  one.write(0x01);
  one.read_bytes(resp, 38);
  one.reset();

  uint32_t count = (uint32_t)resp[35];
  for (int j = 34; j >= 32; j--) {
        count = (count << 8) + (uint32_t)resp[j];
  }
  return count;
}

 

Now all sensor data is placed in the sensor array, we can put them into spark variables for distribution in the cloud this is done in getValues:

void getValues() {
    for(int i=0;i<NUM_SENSORS;i++) {
        if (sensors[i].id != NULL) {
            String strid(sensors[i].id);
            if (strid == "10c1613c000000d5") {
                temperature = sensors[i].value;
            }
            if (strid == "22e8300300000011") {
                temperature1 = sensors[i].value;
            }
            if (strid == "224a3f030000004c") {
                temperature2 = sensors[i].value;
            }
            if (strid == "1d9b1101000000b4") {
                windspeed = sensors[i].value;
            }
            if (strid == "017d384a04000030") {
                winddir = 0;
            }
            if (strid == "018c384a04000075") {
                winddir = 1;
            }
            if (strid == "0174384a040000a6") {
                winddir = 2;
            }
            if (strid == "0177384a040000ff") {
                winddir = 3;
            }
            if (strid == "017a384a040000b5") {
                winddir = 4;
            }
            if (strid == "016b384a040000d9") {
                winddir = 5;
            }
            if (strid == "0183384a04000051") {
                winddir = 6;
            }
            if (strid == "0180384a04000008") {
                winddir = 7;
            }
        }
    }
}

 

Note that the unique addresses are hard coded in this function. This is done for better understanding of the software. In a practical application its better to put these in defines in the upper part of the code, or in a separate header file.

findDevices and getValues are called from the main loop. For testing we now have a delay of 10 seconds, but for the real application this can be much longer, as the minimal probing time from the cloud service (Atomiot) is 5 minutes, but half an hour is much more appropriate. Eventualy a average over this time span can be calculated, but since we want to run the Core on solar power it's better to put it into sleep for a long period.

 

void loop() {
  Serial.println("Spark One-wire weatherstation");
  Serial.println("waiting 10 seconds...");
    delay(10000);


    findDevices();
    getValues();
}

 

After some cleaning of the code I will put the full program listing on github, so please stay tuned.

Next time I will have a look at the hardware of the solar power and battery charger.

Don't hesitate when you have some questions.

  • Sign in to reply

Top Comments

  • DAB
    DAB over 10 years ago +1
    I like the simple design. I remember I got a similar weather kit about 45 years ago that also used mechanical switches to determine the same parameters. It will be interesting to see if you get any switch…
  • gpolder
    gpolder over 10 years ago in reply to DAB +1
    @DAB thanks. I don't see any bounce problems, either with the direction sensors or the counter. I expect this is handled by the 1-wire devices. Gerrit.
  • Former Member
    Former Member over 9 years ago +1
    Hi Gerrit, The article made me look to my 1-Wire weather station again, it was on a shelf for many years. I'm currently trying to get the code running, upto part4 everything works, the final integration…
  • BretCraytor
    BretCraytor over 3 years ago in reply to gpolder

    I worked with this with G McKecknie over on WEEWX.  It is challenging, but dooable.  Take a look over there what we did.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • gpolder
    gpolder over 5 years ago in reply to nikaoj

    Hi nikaoj,

     

    good to see that this project is still valuable. Regarding your problem, you are sure that your circuit is the same as mine, there appear to be a few different versions of it.

    If you are not sure about the switch, you can short the end of the ds2401 to gnd and see if it works.

    Are your reed switches and magnet in order?

     

    best,

    Gerrit

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • nikaoj
    nikaoj over 5 years ago

    Hi Gerrit,

     

    excellent post! I have found my 17 year old weather station, (never used), and after reading your blog I decided to give it a try and connect with Arduino and existing libraries. It works!!!!!

     

    Temperature sensor, wind direction, and activation of the DS2407 switch working with existing libraries.

    But when I try to read DS2401 to capture wind direction I have not been able to read anything. Somehow I think it is linked with the switch. I have tried on and off with switch activation but result are the same. I have arrived to a dead end. Any ideas on what to try next? Thanks for your help. I put the last code I try

    #define DEBUG

     

     

    #include <OneWire.h>

    #include <DS2401.h>

    #include <DS2406.h>

     

    OneWire oneWire(10);

    DS2401 ds24(&oneWire);

     

    OneWireSwitch osw(&oneWire,

                      // Specify the serial number of your DS2407 here.

                      (uint8_t[]){18, 191, 173, 13, 0, 0, 0, 224});

    void setup() {

      Serial.begin(9600);

      delay(10);

      Serial.println("DEBUG:");

     

      if (ds24.init())

      {

        #ifdef DEBUG

        Serial.println(F("Found OneWire Device"));

        #endif // DEBUG

      }

      else

      {

        #ifdef DEBUG

        Serial.println(F("ERROR: No OneWire Device Found"));

        #endif // DEBUG

      }

     

     

      if (ds24.isDS2401())

      {

        #ifdef DEBUG

        Serial.println(F("IS DS2401"));

        #endif // DEBUG

      }

      else

      {

        #ifdef DEBUG

        Serial.println(F("ERROR: Is Not DS2401"));

        #endif // DEBUG

      }

     

     

    }

     

     

    void loop() {

      bool status;

        // Turn on the switch.

        oneWire.reset();

        osw.setSwitchState(false);

        status=osw.getSwitchState();

        Serial.print(status);

        Serial.println("");

        delay(2000);

        oneWire.reset();

        delay(2000);

      Serial.println(ds24.GetSerial());

      delay(2000);

      ds24.Refresh();

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Former Member
    Former Member over 8 years ago

    For anyone interested in producing their own software to monitor MicroLans (multiple 1-Wire chips on a common pair of wires)... it can be done with Lazarus (the "free Delphi") and a simple USB adapter ($25) on a Windows PC... I know... and I suspect (can anyone confirm?) on a Linux box with Lazarus, too... one of the attractions of Linux!

     

    Details at...

     

    http://sheepdogguides.com/lut/dstl2hello_ds18b20.htm

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Former Member
    Former Member over 9 years ago in reply to gpolder

    HI Gerrit,

     

    i van have a look, all THE other piece of code compile for the Photon, the only thing is that in step 5 the code is bases On pieces, when I put everything together it Giles errors about missing variables, i'll give it a try, of you have code that worked on a core then that would help me, I also have cores.

     

    thanks,

    kr,

    rudy

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube