Ultraschallsensor - HB-UNI-Sen-DIST-US mit US-100

Entwicklung und Bau von Hardware aller Art, die im HM-Umfeld eingesetzt werden kann

Moderator: Co-Administratoren

Antworten
hasenpups
Beiträge: 23
Registriert: 30.07.2018, 08:46

Ultraschallsensor - HB-UNI-Sen-DIST-US mit US-100

Beitrag von hasenpups » 23.02.2019, 17:50

Hallo,

Vielleicht hat ja jemand Interesse an einer Firmware mit einem US-100 Ultraschallsensor. Der Sensor hat den Vorteil, dass er bereits ab 2.4V läuft. Ich habe die Firmware von Jerome als Grundlage genommen und entsprechend erweitert.

Code: Alles auswählen

//- -----------------------------------------------------------------------------------------------------------------------
// AskSin++
// 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
// 2018-04-16 jp112sdl Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//- -----------------------------------------------------------------------------------------------------------------------

// define this to read the device id, serial and device type from bootloader section
// #define USE_OTA_BOOTLOADER

#define EI_NOTEXTERNAL
#include <EnableInterrupt.h>
#include <AskSinPP.h>
#include <LowPower.h>

#include <Register.h>
#include <MultiChannelDevice.h>

// Arduino Pro mini 8 Mhz
// Arduino pin for the config button
#define CONFIG_BUTTON_PIN  8
#define LED_PIN            4

#define USE_IO_AS_GND // comment out if normal GND pin is used

// 1 SENSOR
//                  SENSOR  1
byte SENSOR_EN_PINS[]   =  {5}; //VCC Pin des Sensors
byte SENSOR_ECHO_PINS[] =  {7};
byte SENSOR_TRIG_PINS[] =  {6};
byte SENSOR_GND_PINS[] = {9}; // not used if normal GND pin is used

//// 2 SENSOREN
////                  SENSOR  1   2
//byte SENSOR_EN_PINS[]   =  {5,  7}; //VCC Pin des Sensors
//byte SENSOR_ECHO_PINS[] =  {6,  3};
//byte SENSOR_TRIG_PINS[] =  {14, 9};

// battery measurement
#define INTERNAL_VOLTAGE_MEASUREMENT // comment out if universal sensor
#define BATT_EN_PIN        15 //A1
#define BATT_SENS_PIN      17 //A3
#ifdef INTERNAL_VOLTAGE_MEASUREMENT
typedef as::BatterySensor           BatteryType;
#else
typedef as::BatterySensorUni<BATT_EN_PIN, BATT_SENS_PIN>  BatteryType;
#endif

// number of available peers per channel
#define PEERS_PER_CHANNEL  6

// all library classes are placed in the namespace 'as'
using namespace as;

//Korrekturfaktor der Clock-Ungenauigkeit, wenn keine RTC verwendet wird
#define SYSCLOCK_FACTOR    0.88

enum UltrasonicSensorTypes {
  JSN_SR04T,
  MAXSONAR,
  US_100
};

// define all device properties
const struct DeviceInfo PROGMEM devinfo = {
  {0xF9, 0xD6, 0x01},          // Device ID
  "JPDIST0001",                // Device Serial
  {0xF9, 0xD6},                // Device Model
  0x10,                        // Firmware Version
  0x53,                        // Device Type
  {0x01, 0x01}                 // Info Bytes
};

/**
   Configure the used hardware
*/
typedef AskSin<StatusLed<LED_PIN>, BatteryType, Radio<AvrSPI<10, 11, 12, 13>, 2>> BaseHal;
class Hal : public BaseHal {
  public:
    void init (const HMID& id) {
      BaseHal::init(id);
      battery.init(seconds2ticks(60UL * 60) * SYSCLOCK_FACTOR, sysclock); //battery measure once an hour
      battery.low(22);
      battery.critical(19);
    }

    bool runready () {
      return sysclock.runready() || BaseHal::runready();
    }
} hal;


DEFREGISTER(UReg0, MASTERID_REGS, DREG_LOWBATLIMIT, 0x20, 0x21)
class UList0 : public RegList0<UReg0> {
  public:
    UList0 (uint16_t addr) : RegList0<UReg0>(addr) {}

    bool Sendeintervall (uint16_t value) const {
      return this->writeRegister(0x20, (value >> 8) & 0xff) && this->writeRegister(0x21, value & 0xff);
    }
    uint16_t Sendeintervall () const {
      return (this->readRegister(0x20, 0) << 8) + this->readRegister(0x21, 0);
    }

    void defaults () {
      clear();
      lowBatLimit(22);
      Sendeintervall(180);
    }
};

DEFREGISTER(UReg1, 0x01, 0x02, 0x03)
class UList1 : public RegList1<UReg1> {
  public:
    UList1 (uint16_t addr) : RegList1<UReg1>(addr) {}
    bool distanceOffset (uint16_t value) const {
      return this->writeRegister(0x01, (value >> 8) & 0xff) && this->writeRegister(0x02, value & 0xff);
    }
    uint16_t distanceOffset () const {
      return (this->readRegister(0x01, 0) << 8) + this->readRegister(0x02, 0);
    }

    bool sensorType (uint16_t value) const {
      return this->writeRegister(0x03, value & 0xff);
    }
    uint16_t sensorType () const {
      return this->readRegister(0x03, 0);
    }

    void defaults () {
      clear();
      distanceOffset(0);
      sensorType(0);
    }
};

class MeasureEventMsg : public Message {
  public:
    void init(uint8_t msgcnt, uint8_t channel, uint16_t dist, uint8_t volt) {
      Message::init(0x0e, msgcnt, 0x53, (msgcnt % 20 == 1) ? BIDI : BCAST, channel & 0xff, (dist >> 8) & 0xff);
      pload[0] = dist & 0xff;
      pload[1] = volt & 0xff;
    }
};

class MeasureChannel : public Channel<Hal, UList1, EmptyList, List4, PEERS_PER_CHANNEL, UList0>, public Alarm {
    MeasureEventMsg msg;
    uint16_t        distance;
    uint8_t         last_flags = 0xff;

  public:
    MeasureChannel () : Channel(), Alarm(0), distance(0) {}
    virtual ~MeasureChannel () {}

    float US_100_measureDistance(int pin_enable, int pin_trigger, int pin_echo)
    {
      // variables
      float returnValue = 0;
      float echoTime = 0;
      float distance = 0;

      // activate the sensor
      digitalWrite(pin_enable, HIGH);

      // wait some time to boot up
      _delay_ms(250);

      // measure two times, because the first one will fail
      // don't ask me why
      for (int i = 0; i < 2; i++)
      {
        // set the trigger
        digitalWrite(pin_trigger, LOW);
        delayMicroseconds(2);
        digitalWrite(pin_trigger, HIGH);
        delayMicroseconds(50);
        digitalWrite(pin_trigger, LOW);

        // read the distance
        echoTime = pulseIn(pin_echo, HIGH);

        // calculate the distance
        distance = (echoTime * 0.1657) / 10;

        // check if value is valid and break, 400cm is the maximum of the sensor
        //if (distance > 10 && distance < 4000)
        //{
        returnValue = distance;
        // break;
        //}

        // delay some time before the next cycle
        _delay_ms(5);
      }

      // deactivate the sensor
      digitalWrite(pin_enable, LOW);

      // return
      return returnValue;
    }

    void measure() {
      uint32_t m_value = 0;
      if (last_flags != flags()) {
        this->changed(true);
        last_flags = flags();
      }

      switch (this->getList1().sensorType()) {
        case JSN_SR04T:
          digitalWrite(SENSOR_EN_PINS[number() - 1], HIGH);
          _delay_ms(300);
          digitalWrite(SENSOR_TRIG_PINS[number() - 1], LOW);
          delayMicroseconds(2);
          digitalWrite(SENSOR_TRIG_PINS[number() - 1], HIGH);
          delayMicroseconds(10);
          digitalWrite(SENSOR_TRIG_PINS[number() - 1], LOW);
          m_value = pulseIn(SENSOR_ECHO_PINS[number() - 1], HIGH, 26000);
          m_value = (m_value * 1000L / 57874L);
          digitalWrite(SENSOR_EN_PINS[number() - 1], LOW);
          break;
        case MAXSONAR:
          digitalWrite(SENSOR_EN_PINS[number() - 1], HIGH);
          _delay_ms(200);
          m_value = pulseIn(SENSOR_ECHO_PINS[number() - 1], HIGH);
          m_value = (m_value * 1000L / 57874L);
          digitalWrite(SENSOR_EN_PINS[number() - 1], LOW);
          break;
        case US_100:
          m_value = US_100_measureDistance(SENSOR_EN_PINS[number() - 1], SENSOR_TRIG_PINS[number() - 1], SENSOR_ECHO_PINS[number() - 1]);
          break;
        default:
          DPRINTLN(F("Invalid Sensor Type selected"));
          break;
      }

      distance = (m_value > this->getList1().distanceOffset()) ? m_value - this->getList1().distanceOffset() : 0;

      DPRINT(F("MEASURE (")); DDEC(number()); DPRINT(F("): ")); DDEC(m_value); DPRINTLN(F(" cm"));
      DPRINT(F("OFFSET  (")); DDEC(number()); DPRINT(F("): ")); DDEC(this->getList1().distanceOffset()); DPRINTLN(F(" cm"));
      DPRINT(F("DISTANCE(")); DDEC(number()); DPRINT(F("): ")); DDEC(distance); DPRINTLN(F(" cm"));
    }

    virtual void trigger (__attribute__ ((unused)) AlarmClock& clock) {
      measure();
      tick = delay();
      msg.init(device().nextcount(), number(), distance,  device().battery().current());
      device().sendPeerEvent(msg, *this);
      sysclock.add(*this);
    }

    uint32_t delay () {
      return seconds2ticks(max(10, device().getList0().Sendeintervall()) * SYSCLOCK_FACTOR);
    }

    void configChanged() {
      DPRINT(F("*DISTANCE_OFFSET (")); DDEC(number()); DPRINT(F("): ")); DDECLN(this->getList1().distanceOffset());
      DPRINT(F("*SENSOR_TYPE     (")); DDEC(number()); DPRINT(F("): ")); DDECLN(this->getList1().sensorType());
    }

    void setup(Device<Hal, UList0>* dev, uint8_t number, uint16_t addr) {
      Channel::setup(dev, number, addr);

      for (byte i = 0; i < sizeof(SENSOR_EN_PINS); i++) {
        pinMode(SENSOR_ECHO_PINS[i], INPUT_PULLUP);
        pinMode(SENSOR_TRIG_PINS[i], OUTPUT);
        pinMode(SENSOR_EN_PINS[i], OUTPUT);

#ifdef USE_IO_AS_GND
        pinMode(SENSOR_GND_PINS[i], OUTPUT);
        digitalWrite(SENSOR_GND_PINS[i], LOW);
#endif
      }

      sysclock.add(*this);
    }

    uint8_t status () const {
      return 0;
    }

    uint8_t flags () const {
      uint8_t flags = this->device().battery().low() ? 0x80 : 0x00;
      return flags;
    }
};

class UType : public MultiChannelDevice<Hal, MeasureChannel, sizeof(SENSOR_EN_PINS), UList0> {
  public:
    typedef MultiChannelDevice<Hal, MeasureChannel, sizeof(SENSOR_EN_PINS), UList0> TSDevice;
    UType(const DeviceInfo& info, uint16_t addr) : TSDevice(info, addr) {}
    virtual ~UType () {}

    virtual void configChanged () {
      TSDevice::configChanged();
      DPRINT(F("*LOW BAT Limit: "));
      DDECLN(this->getList0().lowBatLimit());
      this->battery().low(this->getList0().lowBatLimit());
      DPRINT(F("*Sendeintervall: ")); DDECLN(this->getList0().Sendeintervall());
    }
};

UType sdev(devinfo, 0x20);
ConfigButton<UType> cfgBtn(sdev);

void setup () {
  DINIT(57600, ASKSIN_PLUS_PLUS_IDENTIFIER);
  if (sizeof(SENSOR_EN_PINS) != sizeof(SENSOR_EN_PINS) || sizeof(SENSOR_ECHO_PINS) != sizeof(SENSOR_ECHO_PINS) || sizeof(SENSOR_TRIG_PINS) != sizeof(SENSOR_TRIG_PINS)) {
    DPRINTLN(F("!!! ERROR: SENSOR PIN ARRAYS PRÜFEN"));
  } else {
    sdev.init(hal);
    DDEVINFO(sdev);
    buttonISR(cfgBtn, CONFIG_BUTTON_PIN);
    sdev.initDone();
  }
}

void loop() {
  bool worked = hal.runready();
  bool poll = sdev.pollRadio();
  if ( worked == false && poll == false ) {
    hal.activity.savePower<Sleep<>>(hal);
  }
}
Die hb-uni-sen-dist-us.xml aus dem Addon muss kopiert und anschließend bearbeitet werden:

Code: Alles auswählen

cp hb-uni-sen-dist-us.xml /usr/local/addons/jp-hb-devices-addon/customized_firmware/
Erweiterung:
<parameter id="SENSOR_TYPE">
<logical type="option">
<option id="JSN-SR04T" default="true" />
<option id="MaxSonar EZ0..4"/>
<option id="US_100"/>
</logical>
<physical type="integer" interface="config" list="1" index="3" size="1"/>
</parameter>
Dateianhänge
Bildschirmfoto 2019-02-23 um 17.43.43.png
Bildschirmfoto 2019-02-23 um 17.43.43.png (23.2 KiB) 270 mal betrachtet
Bildschirmfoto 2019-02-23 um 17.44.12.png
Bildschirmfoto 2019-02-23 um 17.44.12.png (11.29 KiB) 270 mal betrachtet

jp112sdl
Beiträge: 2685
Registriert: 20.11.2016, 20:01
Kontaktdaten:

Re: Ultraschallsensor - HB-UNI-Sen-DIST-US mit US-100

Beitrag von jp112sdl » 12.03.2019, 17:30

Der US-100 funktioniert ohne Anpassungen im Sketch oder XML.
Habe ihn bei mir jetzt selbst auch im Einsatz.

VG,
Jérôme

Antworten

Zurück zu „Hardwareentwicklung und Selbstbau von Aktoren und Sensoren“