0

I have and sketch made for reading a temp/hum sensor once every ten seconds aprox. However, I want to introduce an interruption source to send from my keyboard a magic word to make the sensor be read exactly at that instant.

By checking out the reference on attachInterrupt(), I found only the ways to declare interrupt pins, but nothing related to serial. What you can say about it?

Thanks in advance.

  • Serial.available() or the serialEvents can be used essentially like an interrupt. – dandavis Jun 19 '17 at 18:03
  • @dandavis, not really. Those are polling methods, not interrupts. Those two methods do not "interrupt" other things that your code may be doing. Your code must call available frequently or, if you are using serialEvent, you must make sure that loop doesn't block. However, in the OP's application, polling is sufficient (see gre_gor's answer). – slash-dev Jun 19 '17 at 19:02
  • @slash-dev: regardless of the underpinning, to the dev, they "can be used essentially like"... Specifically, there's no need here for a low-level interrupt when the "main work" is only is done every 10 seconds... – dandavis Jun 19 '17 at 19:26
2

Use millis() for the timing of the temperature reading, then you can read from the serial in between time and won't need to use any interrupts.

unsigned long last_measure = 0;

const byte buffer_size = 16;
char buffer[buffer_size] = "";
byte buffer_i = 0;

// setup() and other stuff

void loop() {
    if (millis() - last_measure > 10000) { // read the temperature like in the "blink without delay" example
        last_measure = millis();
        int value = readSensor();
        Serial.println(value);
    }
    while (Serial.available()) {
        char c = Serial.read();
        if (c == '\n') { // end of line, which means we got the whole string
            if (strcmp(buffer, "magic") == 0) { // compare if it matches the magic word
                int value = readSensor(); // read and print the temperature
                Serial.println(value);
            }
            buffer_i = 0; // reset the index
            buffer[buffer_i] = 0;
        }
        else if (buffer_i < buffer_size-1) { // if the buffer is not full
            buffer[buffer_i++] = c; // add char to buffer
            buffer[buffer_i] = 0; // and null terminate the string
        }
    }
}
0

Here is a logic snippet you can use:

unsigned long timer = 0;

void loop(){
  readSensors();
  while(millis() - timer < 10000){
    if(stringFromSerial == magicWord){
      readSensors();
    }
  }
}
0

Thank you all, guys. I considered your ideas, and then I code this solution. It works fine, right now I'm reading my sensor once every 30 minutes (1,800,000 miliseconds) and whenever I send the magic word. I hope it is useful to you:

void loop(){
if ((millis() - timer < 1800000) && (Serial.available() > 0)){
    magicInput = Serial.readString();
    magicInput.trim(); //Cleans input from \n at the end, otherwise never equals magicInput
    if (magicInput.equals(magicWord)){     //Elegant way to express "=="
      Serial.println();
      Serial.println("  === Your request ==="); //Shows requested measurement
      Serial.println(millis() - timer); //Time since last measurement
      measure(); //
    }
  }

  if (millis() - timer >= 1800000){
    Serial.println();
    Serial.println("===== Normal mode =====");  //Indicates that measurement was not requested by user
    Serial.println(millis() - timer); //Checks that 30 "exact" minutes have run
    mide();
    timer = millis();
  }
}
  • Serial.readString() has a timeout of 1 sec by default, so your response has an unnecessary delay. Use Serial.readStringUntil('\n') instead. – gre_gor Jun 21 '17 at 11:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.