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: 60
Registriert: 30.07.2018, 08:46
Hat sich bedankt: 1 Mal
Danksagung erhalten: 3 Mal

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) 1740 mal betrachtet
Bildschirmfoto 2019-02-23 um 17.44.12.png
Bildschirmfoto 2019-02-23 um 17.44.12.png (11.29 KiB) 1740 mal betrachtet

jp112sdl
Beiträge: 12108
Registriert: 20.11.2016, 20:01
Hat sich bedankt: 848 Mal
Danksagung erhalten: 2148 Mal
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 ☕️

---
Support for my Homebrew-Devices: Download JP-HB-Devices Addon

dlwhm
Beiträge: 20
Registriert: 23.04.2019, 19:09
Hat sich bedankt: 2 Mal
Danksagung erhalten: 1 Mal

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

Beitrag von dlwhm » 15.07.2022, 14:16

jp112sdl hat geschrieben:
12.03.2019, 17:30
Der US-100 funktioniert ohne Anpassungen im Sketch oder XML.
Habe ihn bei mir jetzt selbst auch im Einsatz.
Leider habe ich mit dem US-100 und HB-UNI-Sen-DIST-US.ino keinen Erfolg. Mit dem Sensor werden nur kurze Entfernungen bis maximal 75cm gemessen, alles darüber wird mit 0cm ausgegeben.
Wenn ich diesen Sensor aber mit einem einfachen Arduino Sketch betreibe (mit 3,3V oder auch mit 5V) wie hier unten, funktioniert er auch für weite Entfernungen einwandfrei:

Code: Alles auswählen

// Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  
  // Calculate the distance

  // Median Filter
  /*## LIMITATIONS:
  1) Minimum window size is 3
  2) Maximum window size is 255
  3) Only accepts arduino data type INT  */

  distanceCm = duration * SOUND_SPEED/2;
  filter.in(distanceCm);
  filter_distanceCm = filter.out();
Hat jemand eine Idee, was an der HB-UNI-Sen-DIST-US.ino Software geändert werden kann um das Problem zu beheben?

Antworten

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