~josealberto4444/arduino-quiz

cf02a26d88689ac1f305af03ee1757760440635f — josealberto4444 3 years ago 11fc32f
Add remote control and ditch delay in scrolling

Both scrolling functions are joined in a class and made compatible with other
tasks at the same time (for example, receiving an order to switch the scrolling
direction).
1 files changed, 106 insertions(+), 30 deletions(-)

M quiz/quiz.ino
M quiz/quiz.ino => quiz/quiz.ino +106 -30
@@ 26,11 26,19 @@
// simulator). The purpose is to have a screen where some questions will appear,
// and answer them with a remote control.

#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal_I2C.h>  // Unlicensed, then non-free, so that's the reason for that additional permission in the preamble.
#include <IRremote.h>           // LGPL-2.1 (great, no problem).
// IMPORTANT: Tweak IRremote library for using timer1 instead of timer2, or it
// will conflict with tone function. In the case of Arduino Uno (or any
// ATmega328), this is done (at the moment of writing) uncommenting line 194 and
// commentind 195 in boarddefs.h file.

// Set-up variables
const byte motionPin = 2;          // Motion sensor pin.
LiquidCrystal_I2C lcd(0x27,16,2);  // LCD address and size.
const byte irrecvPin = 10;         // IR receptor pin.
IRrecv irrecv(irrecvPin);          // Initialisation.
decode_results results;

// State-recording variables
volatile bool motion = false;     // Is there any movement that should turn on the device?


@@ 40,41 48,101 @@ bool welcomeScreenState = false;  // Is the welcome screen playing?


// Timing variables
const unsigned short secondsToInactive = 10;
const unsigned short secondsToInactive = 30;
volatile unsigned long prevActiveMillis = 0;
unsigned long prevToneMillis = 0;
unsigned long prevScreenMillis = 0;
byte toneStep = 100;
const byte toneStep = 100;
unsigned short screenStep = 300; // Not a byte because it is modified to a value of 2000

byte toneCounter = 0;
byte screenCounter = 0;


// Functions
void scrollH(String message) {
  // Show a message scrolling horizontally through the first line of the screen
  String spaceFilling = "                ";
  message = spaceFilling + message + spaceFilling;
  for (int i = 0; i < message.length() - 14; i+=2) {
    lcd.setCursor(0, 0);
    lcd.print(message.substring(i, i+16));
    delay(400);
// Scrolling class
class Scroller {
  // Receive a message and scroll it through the screen
  // 
  // If scrolling horizontally, charStep is  the amount of characters in every
  // step.
  // 
  // TODO: Pause.
  // TODO: A kind of manual scrolling, using the remote to move the text.
  // TODO: Change in charStep and speed, saving it for every player.
  unsigned short counter;
  const String spaceFilling = "                ";
  String message;
  unsigned long prevMillis;
  unsigned short updateStep;
  byte charStep;
  char direct;
  
  public:
  Scroller(String msg, char drc) {
    message = spaceFilling + msg + spaceFilling;
    counter = 0;
    charStep = 2;
    direct = drc;
    if (direct == 'H') updateStep = 400;
    if (direct == 'V') updateStep = 1000;
  }
}

void scrollV(String message) {
  // Show a message scrolling vertically through the whole screen
  String spaceFilling = "                ";
  message = spaceFilling + message + spaceFilling;
  for (int i = 0; i < message.length() - 16; i+=16) {
    lcd.setCursor(0, 0);
    lcd.print(message.substring(i, i+16));
    lcd.setCursor(0, 1);
    lcd.print(message.substring(i+16, i+32));
    delay(1000);
  
  void Update() {
    unsigned long currentMillis = millis();
    if (direct == 'H') { // Horizontal scrolling.
      if (counter == 0) {
        lcd.setCursor(0, 0);
        lcd.print(message.substring(counter, counter+16));
        counter += charStep;
        prevMillis = millis();
      } else {
        if (currentMillis - prevMillis >= updateStep) {
          lcd.setCursor(0, 0);
          lcd.print(message.substring(counter, counter+16));
          counter += charStep;
          prevMillis = millis();
          if (counter >= message.length() - 16 + charStep) {
            counter = 0;
          }
        }
      }
    } else if (direct == 'V') { // Vertical scrolling.
      if (counter == 0) {
        lcd.setCursor(0, 0);
        lcd.print(message.substring(counter, counter+16));
        lcd.setCursor(0, 1);
        lcd.print(message.substring(counter+16, counter+32));
        counter += 16;
        prevMillis = millis();
      } else {
        if (currentMillis - prevMillis >= updateStep) {
          lcd.setCursor(0, 0);
          lcd.print(message.substring(counter, counter+16));
          lcd.setCursor(0, 1);
          lcd.print(message.substring(counter+16, counter+32));
          counter += 16;
          prevMillis = millis();
          if (counter >= message.length()) {
            counter = 0;
          }
        }
      }
    }
  }
}
  
  void switchDirection() {
    if (direct == 'H') {
      direct = 'V';
      updateStep = 1000;
    } else if (direct == 'V') {
      direct = 'H';
      updateStep = 400;
      // Clear the second line of the screen.
      lcd.setCursor(0, 1);
      lcd.print(spaceFilling);
    }
  }
};


// Interruption functions


@@ 87,11 155,15 @@ void detectMotion() {



// Set-up
Scroller aMessage("This is quite a long message to show in such a tiny screen. =P", 'H');

void setup() {
  pinMode(motionPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(motionPin), detectMotion, RISING);
  lcd.init();
  lcd.noDisplay();
  irrecv.enableIRIn();
}




@@ 167,8 239,15 @@ void loop() {
  if (screenState) {
    // If you are not welcoming, do your job.
    if (!(welcomeToneState || welcomeScreenState)) {
      lcd.setCursor(0, 0);
      lcd.print(millis()/1000);
      aMessage.Update();
      if (irrecv.decode(&results)) {
        switch (results.value) {
          case 0x1fe48b7:
            aMessage.switchDirection();
            break;
        }
        irrecv.resume();
      }
    }
    
    // Check if it's already time to go to sleep.


@@ 188,8 267,5 @@ void loop() {
      motion = false;
    }
  }
  
  //scrollV("This is quite a long message to show in this tiny screen. =P");
  //scrollH("This is quite a long message to show in this tiny screen. =P");
}