Infrarood bezetmelders met Arduino (DCC)

Plaats reactie

Onderwerp starter
mjdb
Berichten: 133
Lid geworden op: 26 feb 2021 21:48

Infrarood bezetmelders met Arduino (DCC)

Bericht door mjdb »

In het onderwerp "starten met Arduino" wordt gevraagd naar voorbeelden van toepassingen met Arduino.
Om terugvinden van specifieke informatie eenvoudiger te maken heb ik dit nieuwe onderwerp gemaakt.

Bij mijn baan gebruik ik Arduino's om infrarood bezetmelders aan te sturen.

Lees de originele bijdrage: https://www.n-spoorforum.nl/viewtopic.p ... 10#p252510

Marco.


Marco

Digitaal spoor N met Z21 (voorheen DR5000) en Digikeijs modules.
Diverse Arduino's voor wissels en seinen. Zelfbouw DCC decoders.
Ook een paar DTS ground-detectie modules.
Aangestuurd door Koploper.

Onderwerp starter
mjdb
Berichten: 133
Lid geworden op: 26 feb 2021 21:48

Re: Infrarood bezetmelders met Arduino (DCC)

Bericht door mjdb »

PaulRoman schreef: 17 feb 2022 09:14 Of kun je hier de code plaatsen ?
Zie: https://www.n-spoorforum.nl/viewtopic.p ... 69#p253169

Hieronder mijn programma-code. In Arduino terminologie de Sketch.

Marco

Code: Selecteer alles

// Infrared Blockdetection for six IR detectors

const int Debug = 1; // 0 = No Debug-information
// For testing, compile with Debug = 1
// For run-time, compile with Debug = 0
const int BaudRate = 19200; // do not change
unsigned long CurTime;
float CurTimeDec;
unsigned long ShowTime;
const int ShowDelay = 1000; // time between show Debug-lines

const int DetectorCount = 6; // number of detectors to monitor
// Status-led = LED_BUILTIN = pin 13
// External Status-led = pin 2
const int Out_Pin[6] = {3, 4, 5, 6, 7, 8}; // To DCC Ground-detector Unit
const int Led_Pin[6] = {9, 10, 11, 12, A0, A1}; // IR Led near IR receiver
const int IR_Pin[6] = {A2, A3, A4, A5, A6, A7}; // IR transistor for input
const String IR_PinName[6] = {"A2", "A3", "A4", "A5", "A6", "A7"}; // IR transistors 
// A2..A7 Should best be connected to +5V with a 5k resistor. Internal Pullup is not always sufficient.
// Pins A6 and A7 do NOT have internal Pullup.
// Pins A6 and A7 can NOT be used as output

String IR_Result[6][3] = {{"?", "?", "?"}, 
                          {"?", "?", "?"},
                          {"?", "?", "?"},
                          {"?", "?", "?"},
                          {"?", "?", "?"},
                          {"?", "?", "?"}}; // for three measurements per Led
int Out_State[6] = {0, 0, 0, 0, 0, 0}; // 0 = Off; 1 = On
int Out_StatePrev[6] = {0, 0, 0, 0, 0, 0};
String StateText[6] = {"", "", "", "", "", ""};
String StateTextPrev[6] = {"", "", "", "", "", ""};

// Max Allowed Difference-percentage for NOT Active
// If the difference for consecutive measurements is higher
// the detector is active.
// THE OPTIMAL VALUES ARE DEPENDENT ON THE ACTUAL SITUATION.
// So, try and test
const int LimitFactor[6] = {15, 30, 30, 30, 15, 10};

const int Led_React_Time = 3; // ms to turn Led On or Off

int IR_ValueWhenOn[6]; // Current Value When Led is On
int IR_ValueWhenOff[6]; // Current Value When Led is Off
int IR_ValueDifferenceFactor[6]; 

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

void setup() {

  if (Debug == 1) {
    Serial.begin(BaudRate);    
  };

  if (Debug == 1) {
    Serial.println("");
  };

  for (int i=0; i < DetectorCount; i++) {
    if (Debug == 1) {
      Serial.print(i);
      Serial.print(": ");
      Serial.print(IR_PinName[i]);
      Serial.print(" = IR_Pin: ");
      Serial.print(IR_Pin[i]);
      Serial.print("; Out_Pin ");
      Serial.print(Out_Pin[i]);
      Serial.print("; Led_Pin ");
      Serial.println(Led_Pin[i]);
    };
    digitalWrite(Led_Pin[i], LOW); // Led Off
    delay(Led_React_Time);
    digitalWrite(Out_Pin[i], HIGH); // not active
    delay(Led_React_Time);
    pinMode(Led_Pin[i], OUTPUT); // IR Led
    pinMode(Out_Pin[i], OUTPUT); // To S88-Ground-module
    if (i <= 4) {
      pinMode(IR_Pin[i], INPUT_PULLUP); // Analog Pin
      // Not all modules have external pull-up resistors
    }
    else {
      pinMode(IR_Pin[i], INPUT); // Analog Pin      
    };
  };

  pinMode(LED_BUILTIN, OUTPUT); // show countdown to start loop
  // This allows an interrupt to send updates
  for (int i=0; i<4; i++) { //countdown four seconds
    digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
    digitalWrite(2, HIGH);  // turn the external status LED on (HIGH is the voltage level)
    delay(300);             // wait for 3/10 second
    digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
    digitalWrite(2, LOW);   // turn the external status LED off by making the voltage LOW
    delay(700);             // wait for 7/10 second
  } // countdown
  
}; // setup

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

void loop() {

  // Shift previous measurement
  for (int i=0; i<DetectorCount; i++) {
    IR_Result[i][2] = IR_Result[i][1];
    IR_Result[i][1] = IR_Result[i][0];
    IR_Result[i][0] = "?"; // current measurement not yet known
  }; // All Detectors
  
  CurTime = millis();

  // First perform all measurements on all detectors
  for (int i=0; i<DetectorCount; i++) {
    digitalWrite(Led_Pin[i], LOW); // IR Led Off
  };
  delay(Led_React_Time); // wait until IR-transistors are stable
  
  for (int i=0; i<DetectorCount; i++) {
    IR_ValueWhenOff[i] = analogRead(IR_Pin[i]);
  };

  for (int i=0; i<DetectorCount; i++) {
   digitalWrite(Led_Pin[i], HIGH); // IR Led On
  };
  delay(Led_React_Time); // wait until IR-transistor are stable
  
  for (int i=0; i<DetectorCount; i++) {
    IR_ValueWhenOn[i] = analogRead(IR_Pin[i]);
  };
  
  for (int i=0; i<DetectorCount; i++) {
    digitalWrite(Led_Pin[i], LOW); // IR Led Off
  };

  for (int i=0; i<DetectorCount; i++) {
    // A relevant difference (> x %) means that reflection is detected
    IR_ValueDifferenceFactor[i] = (100.0 * (IR_ValueWhenOff[i] - IR_ValueWhenOn[i]) / IR_ValueWhenOff[i]);

    if (IR_ValueDifferenceFactor[i] < LimitFactor[i]) {
      IR_Result[i][0] = "-"; // Negative
    } // No reflection
    else {
      IR_Result[i][0] = "+"; // Positive
    }; // Detection active

    // Now interpret last three results of this detectors
    StateText[i] = IR_Result[i][0] + " " + IR_Result[i][1] + " " + IR_Result[i][2];

    if (StateText[i] == "- - -") {
      Out_State[i] = 0;
      if (Out_State[i] != Out_StatePrev[i]) {
        StateText[i] = "On --> Off";
        digitalWrite(Out_Pin[i], HIGH); // HIGH = Detection Not Active
      };
    }
    else if (StateText[i] == "+ + +") {
      Out_State[i] = 1;
      if (Out_State[i] != Out_StatePrev[i]) {
        StateText[i] = "Off --> On";
        digitalWrite(Out_Pin[i], LOW); // LOW = Detection Active
      };
    };

    if (StateText[i] != StateTextPrev[i]) {
      // Status changed, so show it immediately
      ShowTime = 0;
    };
    
    if (Debug == 1) {
      if (CurTime > ShowTime) {
        Serial.print((CurTime / 1000.0), 3);
        Serial.print(" s ");
        Serial.print(i);
        Serial.print(": ");
        Serial.print(IR_PinName[i]);
        Serial.print("  Off: ");
        Serial.print(IR_ValueWhenOff[i]);
        Serial.print(", On: ");
        Serial.print(IR_ValueWhenOn[i]);
        Serial.print(", \t delta: ");
        Serial.print(IR_ValueWhenOff[i] - IR_ValueWhenOn[i]);
        Serial.print(" \t");
        Serial.print(IR_ValueDifferenceFactor[i]);
        Serial.print("/");
        Serial.print(LimitFactor[i]);
        Serial.print(" \t");
        Serial.println(StateText[i]);
      }; // if ShowTime
    }; // if Debug

    Out_StatePrev[i] = Out_State[i];
    StateTextPrev[i] = StateText[i];
   
  }; // For All Detectors

  if (CurTime > ShowTime) {
    Serial.println();
    ShowTime = CurTime + ShowDelay;    
  };

  // Show Heartbeat to see the system is working
  CurTimeDec = (CurTime/1000.0 - int(CurTime/1000.0));
  
  if (CurTimeDec < 0.7) {
    digitalWrite(LED_BUILTIN, LOW); // turn the led OFF  
  }
  else if (CurTimeDec < 0.8) {
    digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)    
  }
  else if (CurTimeDec < 0.9) {
    digitalWrite(LED_BUILTIN, LOW);
  }
  else {
    digitalWrite(LED_BUILTIN, HIGH); 
  };

}; // Loop

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


Marco

Digitaal spoor N met Z21 (voorheen DR5000) en Digikeijs modules.
Diverse Arduino's voor wissels en seinen. Zelfbouw DCC decoders.
Ook een paar DTS ground-detectie modules.
Aangestuurd door Koploper.
Gebruikersavatar

PaulRoman
Berichten: 150
Lid geworden op: 25 feb 2017 13:48
Locatie: RO

Re: Infrarood bezetmelders met Arduino (DCC)

Bericht door PaulRoman »

Marco, bedankt. Ik was/ben bezig om er een class voor te bouwen. Kan nog wel even duren, want de hardware ligt elders. Dus kan niet testen.
Groet, Paul


Schäßburg an der Kokel
Gebruikersavatar

PaulRoman
Berichten: 150
Lid geworden op: 25 feb 2017 13:48
Locatie: RO

Re: Infrarood bezetmelders met Arduino (DCC)

Bericht door PaulRoman »

Inmiddels heb ik een class "IRSensor" gebouwd, gebaseerd op hetzelfde principe als Marco in zijn draadje schetst. De library kan op de standaard manier in de Arduino IDE worden geimporteerd (sketch > include library > add .ZIP library). De zip-file bevat de source-code, en twee examples. De class is getest met een TCRT5000 infrarood sensor, onder verschillende omgevingslichtcondities. Van felle zonneschijn tot kunstlicht, tot pikdonker. Zie plaatje voor de manier van aansluiten.

Afbeelding

Groet,

Paul
Bijlagen
Lib_IRSensor_1.1.0.zip
(6.19 KiB) 159 keer gedownload


Schäßburg an der Kokel
Plaats reactie