Arduino C Expert to loan their eyes?

Discussion in 'Embedded Systems and Microcontrollers' started by djsfantasi, Nov 21, 2015.

  1. djsfantasi

    Thread Starter AAC Fanatic!

    Apr 11, 2010
    2,801
    831
    aI was hoping that someone familiar with coding for the Arduino would be willing to take a read of my code to see if I am doing anything egregious. I consider myself an accopmplished coder, but two things bring me to ask for this favor. I) I am relatively new to C, II) The Arduino's memory structure is still a bit of a mystery (in a function, is there any advantages to including the static qualifier on constants?) and III) this is a project that I've been working on for someone else (who happens to be my boss) and I want to make the code as bullet-proof as possible.

    So if you can spare a wee bit o'time, Happy Holidays and take a look. If not, I understand and Happy Holidays to you, too.

    A little background. This is for a motivational device that will sit on our desktops. It will look like a rock for that is what represents. a "Rock" or solid business goal. The goal and it's due date will scroll across a two line LCD screen. Occasionally, the rock will say an encouraging message. If you are working on the goal/rock, you can press a button and the rock will acknowledge your effort. However, if the due date approaches, the rock will warn you that you are running out of time. And if you are really close, you will get a stern message. But if you are done, you hold the button down and confirm that you are finished and you will get a congratulatory message and a musical tribute (The Stars and Stripes Forever).

    The Arduino has a real time clock, SD card drive, MP3 player with amplifier, LCD Display and an interrupt driven button for input
    2015-11-07 08.26.42.jpg .
    Code (C):
    1.  
    2. /* Wave Rock v4
    3.    11/17/2015 08:17
    4.  
    5.    Function List
    6.    -------------
    7.    void setup ()
    8.    void loop()
    9.    void backlit(byte myPin)
    10.    void checkButton()
    11.    boolean confirm()
    12.    long Date2Epoch(String myDate)
    13.    void flash()
    14.    boolean readln_Rocks(String& myDate, long& myDateL, String& myMessage)
    15.    void playMessage(char myType, char mySelection)
    16.    void scrollMessage(String myMessage)
    17. */
    18. //*****************************************************************
    19. //*****************************************************************
    20. // include necessary libraries
    21. #include <SPI.h> // for talking to Music Maker shield
    22. #include <Adafruit_VS1053.h> // MusicMaker library
    23. #include <SD.h>  // SD card library
    24. #include <Wire.h> // I2C library
    25. //#include <Adafruit_MCP23008.h>
    26. #include <LiquidCrystal.h> // LCD Display (Backpack) library
    27. #include "RTClib.h" // DS1307 Real Time Clock library
    28. #include <Time.h> // UTC Epoch time converter
    29.  
    30.  
    31. // define the pins used for the MusicMaker shield
    32. #define CLK 13       // SPI Clock, shared with SD card
    33. #define MISO 12      // Input data, from VS1053/SD card
    34. #define MOSI 11      // Output data, to VS1053/SD card
    35. #define SHIELD_CS 7  // VS1053 chip select pin (output)
    36. #define SHIELD_DCS 6 // VS1053 Data/command select pin (output)
    37. #define CARDCS 4     // Card chip select pin
    38. #define DREQ 3       // VS1053 Data request, ideally an Interrupt pin
    39. #define SDCS 10      // SD chip select
    40.  
    41. // Number of rocks to display
    42. const byte MAX_ROCKS = 3;
    43.  
    44. // Constants which define the various states the rock may be in
    45. // #define WARN_DAYS  1209600L // 14 days before due date when in warn condition. WARN_DAYS will always be greater than ALARM_DAYS
    46. // #define ALARM_DAYS  864000L // 10 days before due date when in alarm condition. ALARM_DAYS will always be less than WARN_DAYS
    47. #define WARN_DAYS  30L // Test seconds before the end of the display time
    48. #define ALARM_DAYS 10L // Test seconds before the end of the display time
    49. /* Note that variables whose name ends in "Date" or "Days" are in Unixtime format;
    50. Their units are in seconds. Those variables which end in "Time" are milliseconds
    51. and are used with the millis() function. Hence, their units are in ms.
    52. */
    53.  
    54. // LCD-related values
    55. #define COLUMNS_LCD 16
    56. #define ROWS_LCD 2
    57. #define MESSAGE_LEN 64
    58. const byte   RED_PIN = 28;
    59. const byte GREEN_PIN = 26;
    60. const byte  BLUE_PIN = 24;
    61. // or 44,45,46 for PWM control
    62. // or 24,26,28 for digital control
    63.  
    64. // Button input related values
    65. static const byte BUTTON_PIN = 2;
    66. static const int  STATE_NORMAL = 0; // no button activity
    67. static const int  STATE_SHORT  = 1; // short button press
    68. static const int  STATE_LONG   = 2; // long button press
    69. volatile int resultButton = 0; // global value set by checkButton()
    70.  
    71. // Message parameters
    72. static const byte MAX_MSGS = 3;  // number of messages per state.
    73. static const byte ENC_PROB = 65; // probability of an encouraging  message
    74. static const byte INTERCHAR_DELAY = 125; // pause between characters on scrolling display
    75. static const long DISPLAY_CYCLE_SECS = 120L;
    76.  
    77. // definition of "rock" variables
    78. String rockDuedate[MAX_ROCKS];  // Due date in mm/dd/yy character format
    79. long   rockDuedateL[MAX_ROCKS]; // Due date in UNIX time format
    80. String rockMessage[MAX_ROCKS];  // The actual message (up to  characters)
    81. TimeElements rockDuedate_t; // used to gerate unixtime stamp from date string
    82. long todayDate = 0;
    83.  
    84. // File I/O objects
    85. File RockMessages;
    86. //File RockLogging;
    87.  
    88. // Initialize the Music Maker shield
    89. Adafruit_VS1053_FilePlayer audioplayer =
    90.   Adafruit_VS1053_FilePlayer(SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);
    91.  
    92. // LCD, connected via i2c, default address #0
    93. LiquidCrystal lcd(0);
    94.  
    95. // Initialize the Real Time Clock
    96. RTC_DS1307 rtc;
    97.  
    98.  
    99. //*****************************************************************
    100. //*****************************************************************
    101. void setup () {
    102.   Serial.begin(57600);
    103.   byte indexRock = 0;
    104.  
    105.   randomSeed(analogRead(A0)); // initialize pRNG
    106.  
    107.   // set up the LCD's number of rows and columns:
    108.   Serial.println(F("Initializing LCD & backlight"));
    109.   pinMode(RED_PIN,   OUTPUT); // initializing backlight pins
    110.   pinMode(GREEN_PIN, OUTPUT);
    111.   pinMode(BLUE_PIN,  OUTPUT);
    112.   lcd.begin(16, 2);
    113.   Serial.println(F("Backlight initialized"));
    114.  
    115.   // Print a message to the LCD.
    116.   lcd.clear();
    117.   lcd.setCursor(0, 0);
    118.   lcd.print("  Rock Keeper!");
    119.   Serial.println(F("Rock Master!"));
    120.  
    121.   // initialize input button pins
    122.   Serial.println(F("Initializing Button pin"));
    123.   pinMode(BUTTON_PIN, INPUT_PULLUP);
    124.   attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), checkButton, CHANGE);
    125.   Serial.println(F("Button pin initialized"));
    126.  
    127.   Serial.println(F("Initializing RTC"));
    128.   rtc.begin();
    129.   Serial.println(F("RTC initialized"));
    130.  
    131.   Serial.println(F("inititialize audio player/MusicMaker"));
    132.   audioplayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);  // DREQ int
    133.   if (! audioplayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT)) {
    134.     Serial.println(F("DREQ pin is not an interrupt pin"));
    135.   }
    136.   if (! audioplayer.begin()) { // initialise the music player
    137.     Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
    138.     while (true);
    139.   }
    140.   Serial.println(F("VS1053 found"));
    141.  
    142.   // initializa SD card to read Rocks
    143.   Serial.print(F("Initializing SD card..."));
    144.   pinMode(SDCS, OUTPUT);
    145.   if (!SD.begin(CARDCS)) {
    146.     Serial.println(F("initialization failed!"));
    147.     while (true);
    148.   }
    149.   Serial.println(F("initialization done."));
    150.  
    151.   if (SD.exists("Rock.csv")) {
    152.     Serial.println(F("Rock.csv exists."));
    153.   } else {
    154.     Serial.println(F("Rock.csv doesn't exist."));
    155.     while (true);
    156.   }
    157.  
    158.   Serial.println(F("Initializing -Rocks-"));   // read in rocks from file
    159.   Serial.println(F("Opening Rock.csv..."));
    160.   RockMessages = SD.open("Rock.csv"); // open file
    161.  
    162.   Serial.println(F("read in rocks from file"));
    163.   for (indexRock = 0; indexRock < MAX_ROCKS; indexRock++) { // initialize all "rocks"/ read in from SD card
    164.     readln_Rocks(rockDuedate[indexRock], rockDuedateL[indexRock], rockMessage[indexRock]);
    165.     // Serial.print(rockDuedate[indexRock]);  Serial.print(F("  "));
    166.     // Serial.print(rockDuedateL[indexRock]); Serial.print(F("  "));
    167.     // Serial.println(rockMessage[indexRock]);
    168.   }
    169.   RockMessages.close();
    170.   DateTime now = rtc.now(); // Test
    171.   rockDuedateL[0] = now.unixtime() + 999L; // Test
    172.   rockDuedateL[1] = now.unixtime() + 999L; // Test
    173.   rockDuedateL[2] = now.unixtime() + 999L; // Test
    174.  
    175.   Serial.println(F("-Rocks- initialized"));
    176.   playMessage('5', '0');
    177.   Serial.println(F("Setup complete"));
    178. }
    179.  
    180.  
    181. //*****************************************************************
    182. //*****************************************************************
    183. void loop() {
    184.   // ----------------------------
    185.   char setSelection = '\0';
    186.   boolean ack = false, enc = false, wrn = false, alm = false, cmp = false;
    187.   long endTime = 0;
    188.   long endWait = 0;
    189.   long promptTime = 0;
    190.   long differenceDate = 0;
    191.   byte indexRock = 0;
    192.   byte Bckg = 0;
    193.   static boolean displayTime = true;
    194.   static boolean allDone = false;
    195.  
    196.   while (true) {
    197.     if (allDone) {
    198.       lcd.setCursor(0, 0); lcd.print("Need more rocks!");
    199.       lcd.setCursor(0, 1); lcd.print("You did them all");
    200.       backlit(GREEN_PIN); delay(1000);
    201.       backlit(RED_PIN); delay(1000);
    202.       backlit(BLUE_PIN); delay(1000);
    203.  
    204.     } else {
    205.       // For each rock, perform a cycle of displaying and interacting with the user.
    206.       // ---------------------------------------------------------------------------
    207.       displayTime = true;
    208.       for (indexRock = 0; indexRock < MAX_ROCKS; indexRock++) { // loop through all rocks
    209.         //  for (indexRock = 0; indexRock < 1; indexRock++) { // loop through all rocks
    210.         Serial.print(F("Here at top of loop, indexRock equals "));
    211.         Serial.println(indexRock);
    212.         ack = false; enc = false; wrn = false; alm = false; cmp = false;
    213.         displayTime = true;
    214.         blanklcd(); flash();
    215.         // Only display if it has been displayed for less than 2 hours
    216.         // and it has not been completed.
    217.         while (displayTime && ( rockDuedateL[indexRock] > 0 )) { // if the rock hasn't been completed, display
    218.  
    219.           Serial.println(F("  @rock display loop"));
    220.  
    221.           endTime = (millis() + (DISPLAY_CYCLE_SECS * 1000L));
    222.           promptTime = (millis() + (DISPLAY_CYCLE_SECS * 500L));
    223.           DateTime now = rtc.now(); todayDate = now.unixtime(); if (rockDuedateL[indexRock] > 0 ) rockDuedateL[indexRock] = todayDate + DISPLAY_CYCLE_SECS - 1; // Test
    224.  
    225.  
    226.           // Loop for the display time (DISPLAY_CYCLE_SECS))
    227.           // ***********************************
    228.           while (displayTime) {
    229.             Serial.println(F("    @main display loop ")); // Test
    230.  
    231.             displayTime = (millis() < endTime );
    232.             DateTime now = rtc.now();
    233.             todayDate = now.unixtime();
    234.             differenceDate = rockDuedateL[indexRock] - todayDate; // time left until the due date is reached.
    235.  
    236.             // Prepare for display
    237.             // *******************
    238.             lcd.setCursor(0, 1); //Display the due date on the second line
    239.             lcd.print("                ");
    240.             lcd.setCursor(2, 1);
    241.             if (rockDuedateL[indexRock] != 0) {
    242.               lcd.print(rockDuedate[indexRock]);
    243.             } else {
    244.               lcd.print("Completed!");
    245.             }
    246.  
    247.             // Determine appropriate backlighting
    248.             // ----------------------------------
    249.             if (differenceDate < ALARM_DAYS ) { // figure out background
    250.               Bckg = RED_PIN; // if within ALARM_DAYS of the due date
    251.             } else if (differenceDate < WARN_DAYS ) {
    252.               Bckg = BLUE_PIN; // if within the WARN_DAYS of the due date
    253.             } else {
    254.               Bckg = GREEN_PIN;
    255.             } // otherwise the background is GREEN.
    256.             backlit(Bckg);
    257.  
    258.             // Display due date (or completed)
    259.             if (rockDuedateL[indexRock] != 0) {
    260.               scrollMessage(rockMessage[indexRock]);
    261.             } else {
    262.               lcd.setCursor(0, 0); lcd.print("   Completed!   ");
    263.             }
    264.  
    265.             endWait = millis() + INTERCHAR_DELAY;
    266.             Serial.println(F("      @status check code block"));
    267.             while (millis() < endWait) {
    268.  
    269.               // Check state and play appropriate messages
    270.               //------------------------------------------
    271.               // if the user presses a button, play a encouraging message
    272.               if (((resultButton & STATE_SHORT) == STATE_SHORT ) && !ack) {
    273.                 setSelection = char(random(0, MAX_MSGS + 1) + 0x31);
    274.                 ack = true;
    275.                 playMessage('0', setSelection); // Acknowledgement message
    276.                 resultButton = STATE_NORMAL;
    277.               }
    278.  
    279.               // sometimes at the 1 hour mark (possibly never), play a motivating message
    280.               // if not previously played this cycle
    281.               if ((millis() >= promptTime) && !enc) {
    282.                 enc = true;
    283.                 if (random(0, 101) < ENC_PROB) {
    284.                   setSelection = char(random(0, MAX_MSGS + 1) + 0x31);
    285.                   playMessage('1', setSelection); // Encouragement message
    286.                 }
    287.                 else { //Test
    288.                   Serial.println(F("No encouragement at prompt time")); //Test
    289.                 } //Test
    290.               }
    291.  
    292.               // if the user is in a warn state, play a warning message
    293.               // if not previously played this cycle
    294.               if ((differenceDate < WARN_DAYS) && !wrn) {
    295.                 wrn = true;
    296.                 setSelection = char(random(0, MAX_MSGS + 1) + 0x31);
    297.                 playMessage('2', setSelection); // Warning message
    298.                 backlit(BLUE_PIN);
    299.               }
    300.  
    301.               // if a user is in an alarm state, play a serious message if not
    302.               // previously played this cycle
    303.               if ((differenceDate < ALARM_DAYS) && !alm) {
    304.                 alm = true;
    305.                 setSelection = char(random(0, MAX_MSGS + 1) + 0x31);
    306.                 playMessage('3', setSelection); // Alarm message
    307.                 backlit(RED_PIN);
    308.               }
    309.  
    310.               // if a user completes the rock, confirm and play a congratulatory
    311.               // message if not previously played this cycle
    312.               if (((resultButton & STATE_LONG) == STATE_LONG) && !cmp) {
    313.                 resultButton = STATE_NORMAL;
    314.                 if (confirm()) {
    315.                   cmp = true;
    316.                   setSelection = char(random(0, MAX_MSGS + 1) + 0x31);
    317.                   playMessage('4', setSelection);  // Completion message
    318.                   delay(1000);
    319.                   playMessage('5', '9'); // Stars and Stripes; confirmation message
    320.                   resultButton = STATE_NORMAL;
    321.                   rockDuedateL[indexRock] = 0;
    322.                   displayTime = false;
    323.                 }
    324.               }
    325.             }
    326.             Serial.println(F("      End of status check code block")); // Test
    327.           }
    328.           Serial.println(F("    End of main display loop")); // Test
    329.         }
    330.         Serial.println(F("  End of rock display loop")); //Test
    331.       }
    332.       allDone = ((rockDuedateL[0] == 0 ) &&
    333.                  (rockDuedateL[1] == 0 ) &&
    334.                  (rockDuedateL[2] == 0 ));
    335.       Serial.println(F("End of for loop")); //Test
    336.     }
    337.   }
    338. }
    339.  
    340. //*****************************************************************
    341. void backlit(byte myPin) {
    342.   digitalWrite(RED_PIN,   HIGH);
    343.   digitalWrite(BLUE_PIN,  HIGH);
    344.   digitalWrite(GREEN_PIN, HIGH);
    345.  
    346.   digitalWrite(myPin, LOW);
    347.   delay(1000);
    348.   return;
    349. }
    350.  
    351. //*****************************************************************
    352. void blanklcd() {
    353.   lcd.setCursor(0, 0); lcd.print("                ");
    354.   lcd.setCursor(0, 1); lcd.print("                ");
    355. }
    356.  
    357. //*****************************************************************
    358. void checkButton() {
    359.   /*
    360.    * This function implements software debouncing for a two-state button.
    361.    * It responds to a short press and a long press and identifies between
    362.    * the two states. Your sketch can continue processing while the button
    363.    * function is driven by pin changes.
    364.    */
    365.  
    366.   const long LONG_DELTA = 1000; // hold seconds for a long press
    367.   const long DEBOUNCE_DELTA = 30; // debounce time
    368.   static int lastButtonStatus = HIGH; // HIGH indicates the button is NOT pressed
    369.   int buttonStatus;                       // button atate Pressed/LOW; Open/HIGH
    370.   static long longTime = 0, shortTime = 0; // future times to determine is button has been poressed a short or long time
    371.   boolean Released = true, Transition = false; // various button states
    372.   boolean timeoutShort = false, timeoutLong = false; // flags for the state of the presses
    373.  
    374.   buttonStatus = digitalRead(BUTTON_PIN); // read the button state on the pin "BUTTON_PIN"
    375.   timeoutShort = (millis() > shortTime); // calculate the current time states for the button presses
    376.   timeoutLong = (millis() > longTime);
    377.  
    378.   if (buttonStatus != lastButtonStatus) { // reset the timeouts if the button state changed
    379.     longTime = millis() + LONG_DELTA;
    380.     shortTime = millis() + DEBOUNCE_DELTA;
    381.   }
    382.  
    383.   Transition = (buttonStatus != lastButtonStatus);
    384.   Released = (Transition && (buttonStatus == HIGH)); // for input pullup circuit
    385.   lastButtonStatus = buttonStatus; // save the button status
    386.  
    387.   if ( ! Transition) {
    388.     resultButton =  STATE_NORMAL | resultButton;
    389.     return;
    390.   } // if there has not been a transition, return the normal state
    391.   if (timeoutLong && Released) { // long timeout has occurred and the button was just released
    392.     resultButton = STATE_LONG | resultButton;
    393.   } else if (timeoutShort && Released) { // short timeout has occurred (and not long timeout) and button ws just released
    394.     resultButton = STATE_SHORT | resultButton;
    395.   } else { // else there is no change in status, return the normal state
    396.     resultButton = STATE_NORMAL | resultButton;
    397.   }
    398. }
    399.  
    400. //*****************************************************************
    401. boolean confirm() {
    402.   static const long WAIT = 10000;
    403.   long waitTime = 0;
    404.  
    405.   waitTime = millis() + WAIT ;
    406.   Serial.println(F("in confirm"));
    407.  
    408.   //play confirm message
    409.   // -------------------
    410.   playMessage('5', '1'); // Confirm question message
    411.   // Wait for a response from the user
    412.   // ---------------------------------
    413.   while ((waitTime > millis()) && (resultButton == STATE_NORMAL));
    414.   if (resultButton >= STATE_LONG) {
    415.     // Rock completion confirmed
    416.     // -------------------------
    417.     resultButton = STATE_NORMAL;
    418.     return true;
    419.   }
    420.   else {
    421.     // Completion not confirmed
    422.     // ------------------------
    423.     resultButton = STATE_NORMAL;
    424.     return false;
    425.   }
    426. }
    427.  
    428. //*****************************************************************
    429. long Date2Epoch(String myDate) {
    430.   int fromPtr = 0, toPtr = 0;
    431.   static TimeElements rockDuedate_t;
    432.   static String myMonth;
    433.   static String myDay;
    434.   static String myYear;
    435.   myMonth.reserve(3);
    436.   myDay.reserve(3);
    437.   myYear.reserve(5);
    438.   // Parse month from string
    439.   toPtr = myDate.indexOf('/');
    440.   myMonth = myDate.substring(0, toPtr);
    441.   // Parse day from string
    442.   fromPtr = toPtr + 1;
    443.   toPtr = myDate.indexOf('/', fromPtr);
    444.   myDay = myDate.substring(fromPtr, toPtr);
    445.   // Parse year from string
    446.   fromPtr = toPtr + 1;
    447.   myYear = myDate.substring(fromPtr);
    448.  
    449.   rockDuedate_t.Second = 59;
    450.   rockDuedate_t.Minute = 59;
    451.   rockDuedate_t.Hour = 23;
    452.   rockDuedate_t.Month = myMonth.toInt();
    453.   rockDuedate_t.Day = myDay.toInt();
    454.   rockDuedate_t.Year = myYear.toInt() - 1970;
    455.  
    456.   return makeTime(rockDuedate_t);
    457. }
    458.  
    459. //*****************************************************************
    460. void flash() {
    461.   const byte delayTime = 250;
    462.   const byte flashCount =  6;
    463.   int index = 0;
    464.  
    465.   // flash the backlight
    466.   // -------------------
    467.   for (index = 0; index < flashCount; index++) {
    468.     digitalWrite(  RED_PIN, LOW);
    469.     digitalWrite( BLUE_PIN, LOW);
    470.     digitalWrite(GREEN_PIN, LOW);
    471.     delay(delayTime);
    472.     digitalWrite(  RED_PIN, HIGH);
    473.     digitalWrite( BLUE_PIN, HIGH);
    474.     digitalWrite(GREEN_PIN, HIGH);
    475.     delay(delayTime);
    476.   }
    477. }
    478.  
    479. //*****************************************************************
    480. void playMessage(char myType, char mySelection) {
    481.   static char fileMessage[10] = {"Msg__.mp3"};
    482.   // construct the filename of the message to play
    483.   // ---------------------------------------------
    484.   fileMessage[3] = myType;
    485.   fileMessage[4] = mySelection;
    486.   fileMessage[9] = '\0';
    487.  
    488.   // Stop playing any previous message
    489.   // ---------------------------------
    490.   if (audioplayer.playingMusic) {
    491.     audioplayer.stopPlaying();
    492.     delay(50);
    493.   }
    494.   // Reset the audio player
    495.   // ----------------------
    496.   audioplayer.reset();
    497.   delay(25);
    498.  
    499.   // Play the message specififed by myType and mySelection
    500.   // -----------------------------------------------------
    501.   Serial.print(F("Playing ")); Serial.println(fileMessage);
    502.   audioplayer.setVolume(1, 100); // Set volume for left, right channels. lower numbers == louder volume!
    503.   audioplayer.playFullFile(fileMessage);
    504. }
    505.  
    506. //*****************************************************************
    507. boolean readln_Rocks(String & myDate, long & myDateL, String & myMessage)
    508.  
    509. //   Function to read rocks from SD card
    510.  
    511. {
    512.   static String inputstring = "";
    513.   inputstring.reserve(128);
    514.   byte inputchar = '\0';
    515.   boolean Done = false;
    516.  
    517.   Done = false;
    518.   myDate = "";
    519.   myDateL = 0;
    520.   myMessage = "";
    521.   if (RockMessages.available() == 0) return 0;
    522.  
    523.   Serial.println(F("Reading Rock record"));
    524.   while (! Done) {
    525.     inputchar = RockMessages.read();
    526.     if (inputchar == '|') {
    527.       // pipe found, have chars for date
    528.       myDate  = inputstring;
    529.       myDateL = Date2Epoch(myDate);
    530.       inputstring = "";
    531.       Serial.println("");
    532.       Serial.print(myDate + "   ");
    533.       Serial.println(myDateL);
    534.     } else if (inputchar == 13) {
    535.       // EOL found; last character found
    536.       Serial.println("Found end of record");
    537.       Done = true; myMessage = inputstring;
    538.       inputstring = "";
    539.       inputchar = RockMessages.read(); // clear out LF character
    540.       Done = true;
    541.     } else if ((inputchar < 32) or (inputchar > 125)) {
    542.       //invalid character
    543.     } else {
    544.       // append character to string
    545.       inputstring = String(inputstring + String(char(inputchar)));
    546.     }
    547.   }
    548.   Serial.println("Read rock record");
    549.   return RockMessages.available();
    550. }
    551.  
    552. //****************************************************************
    553. void scrollMessage(String myMessage) {
    554.   static int indexMessage = 0;
    555.   int endex = 0;
    556.   int lastex = 0;
    557.  
    558.   endex = myMessage.length() - COLUMNS_LCD;
    559.   lastex = indexMessage + 15;
    560.  
    561.   lcd.setCursor(0, 0);   lcd.print("                ");
    562.   lcd.setCursor(0, 0);   lcd.print(myMessage.substring(indexMessage, lastex));
    563.   // delay(INTERCHAR_DELAY);
    564.   /* the delay is now performed in main loop, by repeating
    565.    *  the following block of code for a delay defined by INTERCHAR_DELAY */
    566.  
    567.   indexMessage++; if (indexMessage > endex) indexMessage = 0;
    568. }
    569.  
    570.  
    Moderators note : change code tags to C
     
  2. be80be

    Senior Member

    Jul 5, 2008
    431
    57
    Last edited: Nov 21, 2015
  3. nerdegutta

    Moderator

    Dec 15, 2009
    2,515
    785
    Great project.

    How about some pictures and a video when it is done?

    In my ignorance, I couldn't see anything worth mentioning with your code.
     
    djsfantasi likes this.
Loading...