HM-CurrentLoop: 4 bis 20 mA Stromsignaleingang

User stellen ihre Haussteuerung vor

Moderator: Co-Administratoren

Mathias
Beiträge: 1796
Registriert: 03.11.2010, 10:25
System: CCU
Wohnort: Aachen
Hat sich bedankt: 58 Mal
Danksagung erhalten: 262 Mal
Kontaktdaten:

Re: HM-CurrentLoop: 4 bis 20 mA Stromsignaleingang

Beitrag von Mathias » 02.10.2023, 22:07

Ja, genau.

Benutzeravatar
Cupra85
Beiträge: 30
Registriert: 18.11.2022, 20:13
System: CCU
Hat sich bedankt: 3 Mal

Re: HM-CurrentLoop: 4 bis 20 mA Stromsignaleingang

Beitrag von Cupra85 » 04.10.2023, 08:55

Code: Alles auswählen

11:01:23.214 -> ADC: 560
11:01:23.214 -> ADC: 560
11:01:23.214 -> AVG: 560
11:01:23.214 -> DELTA NOT REACHED
11:01:28.611 -> ---
11:01:28.611 -> ADC: 555
11:01:28.611 -> ADC: 562
11:01:28.611 -> AVG: 558
11:01:28.611 -> DELTA NOT REACHED
11:01:34.027 -> ---
11:01:34.027 -> ADC: 553
11:01:34.027 -> ADC: 559
11:01:34.027 -> AVG: 556
11:01:34.027 -> DELTA NOT REACHED
11:01:39.411 -> ---
11:01:39.411 -> ADC: 557
11:01:39.411 -> ADC: 557
11:01:39.451 -> AVG: 557
11:01:39.451 -> DELTA NOT REACHED
11:01:44.816 -> ---
11:01:44.816 -> ADC: 558
11:01:44.816 -> ADC: 556
11:01:44.887 -> AVG: 557
11:01:44.887 -> DELTA NOT REACHED
11:01:50.231 -> ---
11:01:50.231 -> ADC: 560
11:01:50.231 -> ADC: 556
11:01:50.231 -> AVG: 558
11:01:50.231 -> DELTA NOT REACHED
11:01:55.613 -> ---
11:01:55.613 -> ADC: 557
11:01:55.656 -> ADC: 554
11:01:55.656 -> AVG: 555
11:01:55.656 -> OUT: 126
11:01:55.656 -> NOT CHANGED
11:02:01.301 -> ---
11:02:01.301 -> ADC: 560
11:02:01.301 -> ADC: 558
11:02:01.301 -> AVG: 559
11:02:01.301 -> OUT: 127
11:02:01.613 -> SENT

Mathias
Beiträge: 1796
Registriert: 03.11.2010, 10:25
System: CCU
Wohnort: Aachen
Hat sich bedankt: 58 Mal
Danksagung erhalten: 262 Mal
Kontaktdaten:

Re: HM-CurrentLoop: 4 bis 20 mA Stromsignaleingang

Beitrag von Mathias » 04.10.2023, 19:22

Wenn Du die Zeile

Code: Alles auswählen

// ADC reference voltage [V]
constexpr auto ADC_REFERENCE = 1.1;
nach

Code: Alles auswählen

// ADC reference voltage [V]
constexpr auto ADC_REFERENCE = 5;
abänderst, dann muss Du auch

Code: Alles auswählen

  // set ADC reference to 1.1V
  analogReference(INTERNAL);
nach

Code: Alles auswählen

  // set ADC reference to 5V
  analogReference(DEFAULT);
ändern.

Aber warum wollen einige überhaupt den Shunt-Widerstand erhöhen?

Benutzeravatar
Cupra85
Beiträge: 30
Registriert: 18.11.2022, 20:13
System: CCU
Hat sich bedankt: 3 Mal

Re: HM-CurrentLoop: 4 bis 20 mA Stromsignaleingang

Beitrag von Cupra85 » 04.10.2023, 20:08

Das ist mein aktueller Sketch

Code: Alles auswählen

/*
    LOOP CURRENT INPUT (4-20mA) FOR HOMEMATIC
    Copyright (C) 2019 MDZ (info@ccu-historian.de)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <Arduino.h>

// *** CONFIGURATION ***

// minimum valid loop current [mA]
// (12.5% underdrive range is included)
const auto LOOP_CURRENT_MIN = 2.0;

// maximum valid loop current [mA]
// (12.5% overdrive range is included)
const auto LOOP_CURRENT_MAX = 22.0;

// minimum send interval [s]
// (do not stress the duty cycle of the HomeMatic transmitter and central to
// much, e.g. use 60 seconds)
const uint32_t SEND_INTERVAL_MIN = 10;

// pause after startup before first measurement [ms]
const uint32_t STARTUP_PAUSE = 4000;

// pause between measurements [ms]
const uint32_t MEASUREMENT_PAUSE = 5000;

// pause between samples [ms]
const uint32_t SAMPLE_PAUSE = 10;

// number of samples for average calculation (noise reduction)
const int NUM_SAMPLES = 2;

// *** HARDWARE CONFIGURATION ***

// analog pin for reading the voltage drop at the shunt resistor 
// (the shunt resistor should have a value of 47 ohm. the measuring range will
// then be from 0 to 23.4 mA.)
const uint8_t LOOP_CURRENT_PIN = A6;

// pin to trigger a send 
// (pin  on the HM-MOD-EM-8Bit)
const uint8_t TRIGGER_SEND_PIN = 2; // PD2

// HomeMatic 8-bit transmitter HM-MOD-EM-8Bit
// (two ports are needed, because pins PD0 (RX) and PD1 (TX) are already used
// for debug messages.)
// HM-MOD-EM-8Bit   | Arduino Nano V3
// --------------------------------
// INH0             |  8 (PB0)
// INH1             |  9 (PB1)
// INH2             | 10 (PB2)
// INH3             | 11 (PB3)
// INH4             | 12 (PB4)
// INH5             |  5 (PD5)
// INH6             |  6 (PD6)
// INH7             |  7 (PD7)
// DUI30            |  2 (PD2)

// shunt resistor [ohm]
constexpr auto SHUNT = 150.0;

// *** CONSTANTS ***

// blink codes
const uint8_t BLINK_TIME_NOT_ELAPSED  = 1;
const uint8_t BLINK_DELTA_NOT_REACHED = 2;
const uint8_t BLINK_NOT_CHANGED       = 3;
const uint8_t BLINK_SEND              = 4;

// baud rate for monitoring [bits/s]
const unsigned long BAUD_RATE = 115200;

// output start of range
const uint8_t OUT_MIN = 0;

// output end of range
const uint8_t OUT_MAX = 254;

// invalid measurement value
const uint8_t OUT_INVALID = 255;

// ADC reference voltage [V]
constexpr auto ADC_REFERENCE = 3.3;

// map current [mA] to ADC value
template<typename Number> constexpr int mapCurrentToADC(Number current) {
  return SHUNT * current / 1000.0 / ADC_REFERENCE * 1024.0;
}

// ADC value for LOOP_CURRENT_MIN
const int ADC_MIN = mapCurrentToADC(LOOP_CURRENT_MIN);

// ADC value for LOOP_CURRENT_MAX
const int ADC_MAX = mapCurrentToADC(LOOP_CURRENT_MAX);

// invalid ADC value
const int ADC_INVALID = 0x8000;

// minimum delta for detecting a changed raw ADC value
const int ADC_DELTA = 3;

// *** GLOBAL VARIABLES ***

// millisecond of the last sending
unsigned long lastSending;

// last ADC value
int lastAdc;

// last out value
uint8_t lastOut;

// *** FUNCIONS ***

// blinks the LED
void blink(uint8_t times) {
  for (; times; times--) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(125);
    digitalWrite(LED_BUILTIN, LOW);
    if (times > 1) {
      delay(125);
    }
  }
}

// read values from ADC and calculate average
// (returns ADC_INVALID, if value is out of range)
int readAverage() {
  // read values
  int avg = 0;
  for (int cnt = NUM_SAMPLES; cnt; cnt--) {
    int adcValue = analogRead(LOOP_CURRENT_PIN);
    Serial.print(F("ADC: "));
    Serial.println(adcValue);
    if (adcValue < ADC_MIN || adcValue > ADC_MAX) {
      Serial.println("OUT OF RANGE");
      return ADC_INVALID;
    }
    avg += adcValue;
    delay(SAMPLE_PAUSE);
  }
  // calculate average
  avg /= NUM_SAMPLES;
  Serial.print(F("AVG: "));
  Serial.println(avg);
  return avg;
}

// map ADC value to output value
uint8_t mapToOut(int adcValue) {
  if (adcValue == ADC_INVALID) {
    return OUT_INVALID;
  }
  auto out = map(adcValue, ADC_MIN, ADC_MAX, OUT_MIN, OUT_MAX);
  Serial.print(F("OUT: ")); 
  Serial.println(out);
  return out;
}

// set output value
void setOut(uint8_t out) {
  // remark: the output is a short time invalid because the two output ports
  // cannot be set at the same time.
  PORTB = (PORTB & 0b11100000) | (out & 0b00011111);
  PORTD = (PORTD & 0b00011111) | (out & 0b11100000);
  
  // trigger
  // (if the trigger is too short, it will not be recognized by the HM module.)
  digitalWrite(TRIGGER_SEND_PIN, HIGH);
  delay(300); 
  digitalWrite(TRIGGER_SEND_PIN, LOW);

  lastSending = millis();
  lastOut = out;
  Serial.println(F("SENT"));
  blink(BLINK_SEND);
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  // set ADC reference to 3.3V
  analogReference(DEFAULT);
  // throw away first ADC read
  analogRead(LOOP_CURRENT_PIN);

  // HomeMatic 8-bit transmitter
  // set PB0 - PB4 and PD5 - PD7 to output
  DDRB |= 0b00011111;
  DDRD |= 0b11100000;
  // init send trigger pin
  pinMode(TRIGGER_SEND_PIN, OUTPUT);
  digitalWrite(TRIGGER_SEND_PIN, LOW);

  // start message
  Serial.begin(BAUD_RATE);
  Serial.println(F("*** HM-CURRENTLOOP ***"));
  Serial.print(F("ADC_MIN: "));
  Serial.println(ADC_MIN);
  Serial.print(F("ADC_MAX: "));
  Serial.println(ADC_MAX);

  // read and send first time
  delay(STARTUP_PAUSE);
  Serial.println(F("---"));
  int adc = readAverage();
  lastAdc = adc;
  uint8_t out = mapToOut(adc);
  setOut(out);
}

void loop() {
  // read and send, if send interval elapsed and value changed
  delay(MEASUREMENT_PAUSE);
  Serial.println(F("---"));

  // send interval elapsed?
  if (millis() - lastSending < SEND_INTERVAL_MIN * 1000) {
    Serial.println(F("TIME NOT ELAPSED"));
    blink(BLINK_TIME_NOT_ELAPSED);
    return;
  }

  // read ADC
  int adc = readAverage();

  // reduce noise
  if (abs(adc - lastAdc) < ADC_DELTA) {
    Serial.println(F("DELTA NOT REACHED"));
    blink(BLINK_DELTA_NOT_REACHED);
    return;
  }
  lastAdc = adc;

  // map to out
  uint8_t out = mapToOut(adc);

  // value changed?
  if (out == lastOut) {
    Serial.println(F("NOT CHANGED"));
    blink(BLINK_NOT_CHANGED);
    return;
  }

  // send
  setOut(out);
}
Aktuelle Ausgabe (bei der Änderung auf OUT 9 habe ich mit dem Mund Druck auf den Sensor gegeben)

Code: Alles auswählen

20:01:10.899 -> *** HM-CURRENTLOOP ***
20:01:10.899 -> ADC_MIN: 93
20:01:10.899 -> ADC_MAX: 1024
20:01:14.873 -> ---
20:01:14.874 -> ADC: 119
20:01:14.916 -> ADC: 118
20:01:14.916 -> AVG: 118
20:01:14.916 -> OUT: 6
20:01:15.228 -> SENT
20:01:21.097 -> ---
20:01:21.097 -> TIME NOT ELAPSED
20:01:26.245 -> ---
20:01:26.245 -> ADC: 118
20:01:26.245 -> ADC: 118
20:01:26.245 -> AVG: 118
20:01:26.245 -> DELTA NOT REACHED
20:01:31.649 -> ---
20:01:31.649 -> ADC: 117
20:01:31.649 -> ADC: 118
20:01:31.649 -> AVG: 117
20:01:31.649 -> DELTA NOT REACHED
20:01:37.025 -> ---
20:01:37.025 -> ADC: 119
20:01:37.098 -> ADC: 119
20:01:37.098 -> AVG: 119
20:01:37.098 -> DELTA NOT REACHED
20:01:42.430 -> ---
20:01:42.430 -> ADC: 119
20:01:42.501 -> ADC: 119
20:01:42.501 -> AVG: 119
20:01:42.501 -> DELTA NOT REACHED
20:01:47.835 -> ---
20:01:47.835 -> ADC: 127
20:01:47.906 -> ADC: 131
20:01:47.906 -> AVG: 129
20:01:47.906 -> OUT: 9
20:01:48.188 -> SENT
20:01:54.074 -> ---
20:01:54.074 -> TIME NOT ELAPSED
20:01:59.197 -> ---
20:01:59.197 -> ADC: 117
20:01:59.197 -> ADC: 119
20:01:59.197 -> AVG: 118
20:01:59.197 -> OUT: 6
20:01:59.509 -> SENT
20:02:05.412 -> ---
20:02:05.412 -> TIME NOT ELAPSED
Die Ausgabe find ich sieht besser aus, aber bei Druck müste die Ausgabe sich mehr erhöhen als von OUT 6 auf OUT 9.

Mathias
Beiträge: 1796
Registriert: 03.11.2010, 10:25
System: CCU
Wohnort: Aachen
Hat sich bedankt: 58 Mal
Danksagung erhalten: 262 Mal
Kontaktdaten:

Re: HM-CurrentLoop: 4 bis 20 mA Stromsignaleingang

Beitrag von Mathias » 04.10.2023, 21:59

Cupra85 hat geschrieben:
04.10.2023, 20:08
Die Ausgabe find ich sieht besser aus, aber bei Druck müste die Ausgabe sich mehr erhöhen als von OUT 6 auf OUT 9.
Zusätzlich zu der Ausgabe auf der seriellen Konsole müsstest Du dann mal den Strom durch den Sensor messen.

Benutzeravatar
Cupra85
Beiträge: 30
Registriert: 18.11.2022, 20:13
System: CCU
Hat sich bedankt: 3 Mal

Re: HM-CurrentLoop: 4 bis 20 mA Stromsignaleingang

Beitrag von Cupra85 » 05.10.2023, 17:34

Bei OUT 6 stehen 4mA an (ohne Druck)
Bei OUT 10 stehen 4,5mA an (Mund Druck)

Mathias
Beiträge: 1796
Registriert: 03.11.2010, 10:25
System: CCU
Wohnort: Aachen
Hat sich bedankt: 58 Mal
Danksagung erhalten: 262 Mal
Kontaktdaten:

Re: HM-CurrentLoop: 4 bis 20 mA Stromsignaleingang

Beitrag von Mathias » 05.10.2023, 21:56

Eine von diesen Einstellungen muss noch falsch sein:

Code: Alles auswählen

// shunt resistor [ohm]
constexpr auto SHUNT = 150.0;

Code: Alles auswählen

// ADC reference voltage [V]
constexpr auto ADC_REFERENCE = 3.3;

Code: Alles auswählen

  // set ADC reference to 3.3V
  analogReference(DEFAULT);
Wobei ich hier auch bezweifele, dass DEFAULT tatsächlich 3,3V bedeutet.

Oder Shunt-Widerstand ist nicht 150 Ohm, wie angegeben.

Benutzeravatar
Cupra85
Beiträge: 30
Registriert: 18.11.2022, 20:13
System: CCU
Hat sich bedankt: 3 Mal

Re: HM-CurrentLoop: 4 bis 20 mA Stromsignaleingang

Beitrag von Cupra85 » 06.10.2023, 15:12

Hab mir nochmal alles durchgelesen. Du hast weiter vorne geschrieben:
Ich sehe gerade, dass der Arduino Nano 3.x keine 3,3V als Referenzspannung unterstützt
Könnt auch daran liegen? Demnach bräuchte ich ja für eine Vref von 5V ein 220Ohm als R1.

Der Arduino wird ja über 12V versorgt. Sehe ich das richtig, dass nur 5V Arduino nur mit Vref 5V, 3,3V Arduino nur mit 3,3V und alles andere nur mit Vref 1,1V betrieben werden kann?
https://www.arduino.cc/reference/de/lan ... reference/

Antworten

Zurück zu „Projektvorstellungen“