OpenRoberta / openroberta-lab

The programming environment »Open Roberta Lab« by Fraunhofer IAIS enables children and adolescents to program robots. A variety of different programming blocks are provided to program motors and sensors of the robot. Open Roberta Lab uses an approach of graphical programming so that beginners can seamlessly start coding. As a cloud-based application, the platform can be used without prior installation of specific software but runs in any popular browser, independent of operating system and device.
Apache License 2.0
123 stars 118 forks source link

Add pulseIn feature for arduino #765

Open philippmaurer opened 4 years ago

philippmaurer commented 4 years ago

Is your feature request related to a problem? Please describe. Some Arduino sensors work by reading a pulse for HIGH and LOW on a digital pin.

Describe the solution you'd like

Describe alternatives you've considered Because the pulse is read in micro seconds, it is not possible to read the pulse with a timer.

Additional context Arduino pulseIn function: https://www.arduino.cc/reference/en/language/functions/advanced-io/pulsein/

boonto commented 4 years ago

As there was another request I took a quick look on how to implement it using the existing "read pin" block. We could add the two PULSEHIGH and PULSELOW modes to the sensor definitions of the out sensor and add two very ugly ifs to the special OUT case in the robSensors.js:

...
// this is a special case for arduino 
if (sensor.title === 'OUT') {
    var configBlockName = option.toLowerCase() + 'out';
    var dropDownPorts = getConfigPorts(configBlockName);
    if (option === 'PULSEHIGH' || option === 'PULSELOW') {
        dropDownPorts = getConfigPorts('analogout');
    }
    var fieldSensorPort = thisBlock.getField('SENSORPORT');
    thisBlock.dependConfig.type = configBlockName;
    if (option === 'PULSEHIGH' || option === 'PULSELOW') {
        thisBlock.dependConfig.type = 'analogout';
    }
    ...

As this is not the nicest approach we should discuss this soon.

el-voss commented 1 year ago

This feature seems to have been a bit forgotten, but I would really appreciate to see this implemented. With the Calliope this possibility already exists - maybe a transferable implementation for the Arduino can be found there:

grafik

On the one hand, this feature would be helpful for the ultrasonic sensor, which could then also be read out manually. On the other hand, this would make it possible to measure the CO2 concentration with the MH-Z19B sensor.

Example for reading the MH-Z19B sensor with pulseIn: https://funduino.de/nr-51-co2-messung-mit-arduino-co2-ampel

Personally I had used another formular according to the data sheet of the MH-Z19B sensor (see below). The only thing missing is the pulseIn-command.

/* Measures CO2 Level of the air and indicates it with colours
 *  Data Sheet of CO2-Sensor MH-Z19B:
 *  https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf
 */

#define CO2_PWM 4

unsigned long preheatTime = 3*60*1000L;    // sensor needs 3min for heating up
int range = 5000;               // sensor measures from 0ppm to 5000ppm

long newppm = 0;                // variable for storing the ppm value

int interval = 10000;            // time between two measurements in ms

void setup() {
  Serial.begin(9600);
  pinMode(CO2_PWM, INPUT);

  Serial.println("Testing MH-Z19B with PWM Interface");

}

void loop() {

  // measure co2 level
  newppm = getCO2();

  if ( newppm == -1) {    // handle error of measurement

    // output on serial monitor
    Serial.println("Measure failed, now pausing, then restarting");

    // wait for the time left, when subtracting the measurement time
    delay( interval - 10 * interval / (2*10) );

    // skip next steps of this loop turn
    return;
  }

   // output of co2 level on serial monitor
  Serial.println("CO2 value: " + String(newppm) + "ppm");
  Serial.println();
  Serial.println();

  // wait
  delay(interval);
}

/* Measure CO2 in ppm by analyzing the pwm-pin according to p. 6 in the data sheet (see header for link)
 * returns -1, if measure didn't succeed
 */
long getCO2(void) {

  long th, tl, ppm_pwm = 0;

  byte counter = 5;         // try to measure five times, otherwise report an error
  do {
    th = pulseIn(CO2_PWM, HIGH, 1004000) / 1000;
    if (th == 0) {
      Serial.println("Measure failed.");
      counter--;
    }
    tl = 1004 - th;
    ppm_pwm = range * (th - 2) / (th + tl - 4);
  } while (th == 0 && counter > 0);

  if ( counter == 0) return -1;
  return ppm_pwm;
}