[solved] Changing variable in code with the loop

Hello all,

I am currently working on a lasergrid game which is part of a escape room for the scouts. The idea is that they need to pass a lasergrid to get to a keypad with display to input a code which would give them a code to open a numbered lock on the door. Since this game is meant to be possible to be played multiple times I wanted to add a master code to change the password. So far so good the only thing I have an issue with is that this code is not stored in the char array when resetting or powercycling. I have been looking on the web to find the answer for this but it either is to difficult for me to understand at the present moment with the skill level I have, or it is not possible.

This is still work in progress but any help will be much appreciated it is mostly the part from Void passwordchange (at the bottom) where I want to store the changed array Master in the flash or EEPROM (I am not really clear on the location this information is stored).

Thanks again for taking the time to read this and helping me out. I will put the code in the next comment.

Kind regards,
Jim de Groot

//***********************************
//OLED display
//***********************************
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"

// 0X3C+SA0 - 0x3C or 0x3D
#define I2C_ADDRESS 0x3C

// Define proper RST_PIN if required.
#define RST_PIN -1

SSD1306AsciiWire oled;

//***********************************
//Neopixel
//***********************************

#include <Adafruit_NeoPixel.h>
#define PIN 4
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);
/*
  red = strip.Color(255,0,0);
  green = strip.Color(0,255,0);
  blue = strip.Color(0,0,255);
*/
//***********************************
//NR24L01
//***********************************
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8);

const byte rxAddr[6] = "00001";
char message;
bool flagcont;
bool flagstatus;
char text[32];
char starttext[32] = "START";
char alarmtext[32] = "alarm";
char oktext[32] = "OK";
bool done = false;

//***********************************
//keypad
//***********************************

unsigned long key;
char push;
char pushold;
unsigned long keycheck;
const int bounce = 5;

//***********************************
//password
//***********************************

#define Password_Lenght 7 // Give enough room for six chars + NULL char
char Data[Password_Lenght]; // 6 is the number of chars it can hold + the null char = 7
char Master[Password_Lenght] = "123456";
byte data_count = 0, master_count = 0;
bool Pass_is_good;
char customKey;

//***********************************
//password change
//***********************************
#define Change_Length 7
char Change[Change_Length] = "012345";
char Changelog[Change_Length];
byte change_count = 0, changemaster_count = 0;
bool changeflag = false;

void setup()
{
  //***********************************
  //OLED display setup
  //***********************************
  Wire.begin();
  Wire.setClock(400000L);

#if RST_PIN >= 0
  oled.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
#else // RST_PIN >= 0
  oled.begin(&Adafruit128x64, I2C_ADDRESS);
#endif // RST_PIN >= 0

  oled.setFont(Adafruit5x7);

  //********************************************************
  //Neopixel setup
  //********************************************************
  //strip.begin();
  //strip.show();

  //********************************************************
  //setup serial interface
  //********************************************************

  // while (!Serial);
  Serial.begin(9600);

  //********************************************************
  //radio setup
  //********************************************************
  radio.begin();
  radio.openReadingPipe(0, rxAddr);

  radio.startListening();

}


void loop()
{
  //********************************************************
  //radio receive and create flags for continued functions
  //********************************************************

  if (radio.available())
  {
    char text[32] = {0};
    radio.read(&text, sizeof(text));
    //Serial.println(text);
    if (!strcmp(text, starttext) && done == false) { //check if START message has been send by lasermodule, done is used to prevent multiple executions of the code
      flagcont = true; // if executed set flagcont (flag to continue code) to 1 (or true)
      oled.clear();
      oled.println("password?"); // print please give password:
      done = true; // set flag that code has been executed to prevent executing it multiple times
    }

    if (!strcmp(text, alarmtext)) {  // check if ALARM message has been send by lasermodule
      flagstatus = 1; // set alarmflag to true
    }

    if (!strcmp(text, oktext)) { // check if OK has been send by lasermodule to reset the Alarm
      flagstatus = 0; // set alarmflag to false
    }
  }

  while (flagcont == 0) { // while loop to wait untill lasermodule is ready so it keeps returning to the beginning of the void loop if it is started alarm can be activated
    return;
  }

 if (flagstatus == 1) {
    oled.clear();
    oled.set2X();
    oled.println("Alarm!");
    delay(5000); //stop all activity for 2 minutes
    datareset(Data[7]); // perform datareset loop so code needs to be inputted again
    oled.clear();
    oled.set1X();
    oled.println("password?");
  }
 

  //***********************************
  //keypad readout
  //***********************************
  key = analogRead(A0);
  if (key > 0) {
    delay(bounce);
    keycheck = analogRead(A0);
    if (key == keycheck) {
      if (key >= 1005 &&  key <= 1020) {
        push = '1';
      }
      if (key >= 206 &&  key <= 209) {
        push = '2';
      }
      if (key >= 109 &&  key <= 115) {
        push = '3';
      }
      if (key >= 75 &&  key <= 81 ) {
        push = 'A';
      }
      if (key >= 424 &&  key <= 428) {
        push = '4';
      }
      if (key >= 159 &&  key <= 164) {
        push = '5';
      }
      if (key >= 99 &&  key <= 104) {
        push = '6';
      }
      if (key >= 70 &&  key <= 73) {
        push = 'B';
      }
      if (key >= 301 &&  key <= 304) {
        push = '7';
      }
      if (key >= 137 &&  key <= 141) {
        push = '8';
      }
      if (key >= 89 && key <= 93) {
        push = '9';
      }
      if (key >= 65 && key <= 69) {
        push = 'C';
      }
      if (key >= 219  && key <= 224) {
        push = '*';
      }
      if (key >= 116 && key <= 119) {
        push = '0';
      }
      if (key >= 81 && key <= 84) {
        push = '#';
      }
      if (key >= 60 && key <= 64) {
        push = 'D';
      }
    }

  }

  if (push != pushold) {


    //***********************************
    //uncomment this debug if keys not registered and check in serial monitor
    //***********************************
    /*Serial.print("analog reading: ");
      Serial.print(key);
      Serial.print("  ");
      Serial.println(push);
      Serial.println(pushold);
      Serial.println("************");
    */

    pushold = push;
    if (changeflag == true)
    {
      passwordchange(push);
    }
 
  else
    {
      password(push); // send data from push to password function
    }
  }

  }


  void password(char keypress) {

    Data[data_count] = keypress; // store char into data array
    oled.print(Data[data_count]); // print char at said cursor
    data_count++; // increment data array by 1 to store new char, also keep track of the number of chars entered

    if (data_count == Password_Lenght - 1) // if the array index is equal to the number of expected chars, compare data to master
    {
      oled.println();
      oled.println("*************");
      oled.println("Password is ");

      if (!strcmp(Data, Change))
      {
        oled.clear();
        changeflag = true;
        oled.println("password change");
        oled.println("give new password");
        return;
      }

      if (!strcmp(Data, Master)) // equal to (strcmp(Data, Master) == 0)
      { oled.print("Good");
      }
      else
      {
        oled.println("Bad");
        delay(2000);
        for ( int i = 0; i < sizeof(Data);  ++i )
          Data[i] = (char)0;
        data_count = 0;
        oled.clear();
        oled.println("password?");
      }

      delay(1000);// added 1 second delay to make sure the password is completely shown on screen before it gets cleared.
    }
  }




  void datareset (char Data[7]) {
    for ( int i = 0; i < sizeof(Data);  ++i )
      Data[i] = (char)0;
    data_count = 0;
  }

  void passwordchange(char keypr) {

    Changelog[change_count] = keypr;
    oled.print(Changelog[change_count]);
    change_count++;


    if (change_count == Change_Length - 1)
    {
      oled.clear();
      oled.println("password set");
      delay(2000);
      for (int i = 0; i < sizeof(Master); ++i){
        Master[i] = Changelog[i];
      }
         
    oled.clear();
    changeflag = false;
    oled.println("password?");
      
      for ( int i = 0; i < sizeof(Data);  ++i ){
          Data[i] = (char)0;
        data_count = 0;}
       }       
  }

Just put it in EEPROM as well when you change it and read it back in setup() :slight_smile:

PS Change the defines to const's :wink:

Could you give an example on how to place something in the EEPROM?

Is the advantage of using the Const to save RAM and not accidentally change the value?

Thanks for your help!

Could you give an example on how to place something in the EEPROM?

Did you even look at the reference page for EEPROM?

Can you guess whether read() or write() would be the appropriate method to use to put something into EEPROM?

Can you make a guess as to what the inputs need to be? Something like where to store the data, and what data to store....

Instead of

#define PIN 4

do

const byte pin = 4;

Does not save memory, probably compiles to the same. But if you make an error it's a heck more readable.

Some thing like

#define PIN 4;

for example gives pretty complicated errors.

Also, use better variable names. Better a longer but describtive one than a short one. So pin of what? Aka, 'NeoPixelPin' would be a better name.

And for EEPROM read of password:

#include <EEPROM.h>

const byte PasswordLength = 7;
const byte PasswordEepromAddress = 0;

char password[PasswordLength] = "";

void setup(){
  for(byte i = 0; i < PasswordLength; i++){
    password[i] = EEPROM.read(PasswordEepromAddress + i);
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

For writing (only needed when changing it) it's kind of the same. Note, this example uses EEPROM address 0 though 6 including. 'PasswordEepromAddress' only holds the start address. But you have to pick a spot in EEPROM. If the password is the only thing you can stick with 0 like the example.

Note two, the null terminator is also written to EEPROM. You don't really need that but hey, it's easy.

Dear Septillion,

Thank you so much for your help this makes it a lot more understandable. This example makes it very clear. Just a little more code (and soldering) and hopefully this project is finished.

The variable names which are short are mostly due to the fact that these are direct copies from examples and are not yet in use and tweaked, but I will take your advice to heart.

Thanks again for your awesome support!

Kind regards,
Jim

Next time, don't copy it but use it as an inspiration with good varaible names. Makes the code a lot more readable and A LOT easier to debug because of that. Especially if you're new copying seems easy but in the long run (aka, more than blinking a led) it's easier to have understandable code :slight_smile:

Definitely! I already butchered/changed a lot of the code and added some of my own I am pretty proud at how far I have come already, but realise I am still in my first babysteps. Learning from books and internet is also pretty difficult I am trying to found a electronics club at my work were a lot of people who has the same interest to join and learn from eachother (and get a experienced coder from our R&D to teach). As long as that is not yet there we need to learn it ourselves :wink: .