如何更改当前代码以从2个不同的OneWire设备读取?

时间:2016-02-18 14:13:11

标签: arduino nodemcu

我已经获得了从OneWire温度设备DS18b20读取的代码。我想在同一个引脚上添加另一个传感器,但不太确定如何做到最好。我自己没有写这个代码。我正在使用NodeMCU devkit v0.9。下面的代码只是完整代码的一部分,并且有单独的脚本/选项卡。如果我应该添加任何其他内容,请告诉我。任何帮助是极大的赞赏。

#include <Arduino.h> // not automatically included?
#include <OneWire.h> // for temp sensor
#include <Wire.h>    // I2C for ADC & RTC
#include <DHT.h>     // Humidity sensor    
#include "sens.h"

#define TEMP_PIN D2  // Where DS18B20 is connected
#define ADDR_LEN 8   // 1-Wire address length // NOT SURE WHAT THESE DO!!
#define DATA_LEN 9   // 1-Wire data length // NOT SURE WHAT THESE DO!!
#define HUMI_PIN D1  // Where the DHT11 is
#define RTC_ADDR 0x68  // Clock's I2C address
#define ADC_ADDR 0x48  // ADC's I2C address
#define SDA  D3    // I2C pins
#define SCL  D4

OneWire ow(TEMP_PIN); // Setup 1-Wire
byte addr[ADDR_LEN];  // To store 1-Wire address
byte data[DATA_LEN];  // To store 1-Wire data
DHT dht(HUMI_PIN, DHT11);  // Setup DHT

String leading0(const int c) {
  // Add a leading zero when stringifying a byte, used for the date
  return (c < 10) ? ("0" + String(c)) : String(c);
}

byte bin2bcd( const byte bin ) {
  // does as the name suggests, RTC uses BCD
  return (bin / 10 * 16) + (bin % 10);
}

byte bcd2bin( const byte bin ) {
  // does as the name suggests, RTC uses BCD
  return (bin / 16 * 10) + (bin % 16);
}

void senssetup() {
  // Setup sensors, called in setup()
  dht.begin();
  Wire.begin(SDA, SCL);
}

float gettemp() {
  int i = 0;
  ow.reset_search();
  do {} while (!ow.search(addr) && i++ < 0xff);
  // Search for 1-Wire devices
  if (i == 0x100) {
    if (debug) Serial.println("No devices found!");
    // Nothing connected
    return 0;
  }
  if (OneWire::crc8(addr, 7) != addr[7]) {
    if (debug) Serial.println("CRC 1 failed!");
    // Checksum thing when getting device's address
    return -1;
  }
  if (addr[0] != 0x10 && addr[0] != 0x28) {
    if (debug) Serial.println("Not a DS18B20");
    // Wrong 1-Wire device
    return -2;
  }
  ow.reset();
  ow.select(addr);
  ow.write(0x44, 0);
  // HEX 44 tells it to convert temperature to readable binary
  delay(1000);
  // It takes ~750ms to convert data, 1s is used to be safe (1s is used in the default library too)
  if (!ow.reset()) {
    if (debug) Serial.println("Device not present");
    // Device has disconnected or broken during conversion?
    return -3;
  }
  ow.select(addr);
  ow.write(0xbe, 0);
  // Tells it we're reading
  for (i = 0; i < DATA_LEN; i++) {
    data[i] = ow.read(); // Read data
  }
  if (debug && OneWire::crc8(data, 8) != data[8])
    Serial.println( "CRC Check 2 failed" );
  // Checksum on data; this fails sometimes, I don't know why
  // temperature is always at the right value so ignore it
  int dat =  ((data[1] << 8) | data[0]);
  if (dat > 32767)
    dat -= 65536;
    // 16 bit data in 2's complement has a sign
    return dat / 16.0;
    // last 4 binary digits are fractional
}

1 个答案:

答案 0 :(得分:2)

您应该将搜索部分与获取温度部分分开。

注意:我没有进入NodeMCU,所以在使用它之前你必须使它适应那种语言。我会用C。

例如,您可以使用函数获取温度传感器的所有地址并将它们放在地址数组中:

struct Animal {
    let name: String
    let traits: AnimalTraits
}

let salmon = Animal(name: "Salmon", traits: .Fish)

salmon.traits.contains(.HasFur) //false
salmon.traits.contains(.HasScales) //true

let bizarro = Animal(name: "Fictional Animal", traits: [.LaysEggs, .GivesLiveBirth])

然后你可以修改你的功能以获得第i个传感器的温度:

#define MAX_DEVICES 5
byte addresses[MAX_DEVICES][ADDR_LEN];
byte numOfAddresses;

void getAllAddresses()
{
    numOfAddresses = 0;
    ow.reset_search();
    byte address[ADDR_LEN];

    while (ow.search(address) && (numOfAddresses < MAX_DEVICES))
    {
        if ( OneWire::crc8( address, 7 ) != address[7] )
            continue; // CRC 1 failed

        if ( address[0] != 0x10 && address[0] != 0x28 )
            continue; // Not a DS18B20

        byte i;
        for (i = 0; i < ADDR_LEN; i++)
            addresses[numOfAddresses][i] = address[i];
        numOfAddresses++;
    }

    if (debug)
    {
        Serial.print("Found ");
        Serial.print(numOfAddresses);
        Serial.println(" temperature sensors");
    }
}

(只需通过调用float gettemp(byte index) { if (index >= numOfAddresses) { if (debug) Serial.println( "Index not valid" ); return -200; // Don't use 0, -1, ..., since they are valid temperatures } ow.reset(); ow.select(addresses[index]); ow.write(0x44, 0); // HEX 44 tells it to convert temperature to readable binary [...] 替换每个addr来电。

在您的代码中,您不必致电addresses[index],而是需要为第一个传感器调用gettemp,为第二个传感器调用gettemp(0),依此类推。

在第一次调用gettemp之前,您需要调用gettemp(1),否则它将始终返回-200。您可以在启动时或每X秒或每次测量时调用它,这完全取决于您