Comparing Strings in Arduino C++? - c++

I'm currently writing some arduino code for a GUI with with Keypad and 16x2 LCD implementation. Part of my program requires a password to be entered before certain content on the Arduino can be accessed, however I can't seem to figure out how to get my saved password and given input to work properly.
String pswd = "0000";
char* Input(int Length, byte clmn, byte row) {
char output[Length];
int i = 0;
while (i < Length) {
char KeyPress = keypad.getKey();
lcd.setCursor(clmn,row);
if (KeyPress == '0' ||
KeyPress == '1' ||
KeyPress == '2' ||
KeyPress == '3' ||
KeyPress == '4' ||
KeyPress == '5' ||
KeyPress == '6' ||
KeyPress == '7' ||
KeyPress == '8' ||
KeyPress == '9') {
output[i] = KeyPress;
lcd.print(KeyPress);
i++;
clmn++;
lcd.setCursor(i+1,0);
lcd.cursor();}
}
delay(3000);
Serial.println(output);
return output;
}
bool Is_Psswrd() {
bool Passed = false;
char *Test;
String test;
CH2 = true;
while (CH2) {
say("Password: ",0,0);
Test = Input(4, 10, 0);
test = Test;
if (test==pswd) {
Passed = true;
CH2 = false; }
else {
for(int i = 0; i < 3; i++) {
lcd.clear();
say("Incorrect ",0,0);
delay(200); } }
}
return Passed;
}
void setup() {
Is_Psswrd();
}
void loop() {}
I've tried alot of different things for saving, inputting, and checking characters, some more jankier than others. My original plan was to save all variables as char* variables and use the strcmp() function, but that didn't seem to work (strcmp() kept outputting "144") and I learned I needed const char* to make the function work properly. I've given the code I believe is needed to access the issue, but if you need the rest of the code I can paste it.
I am very new to C++. Most of my code is written in Java. Can someone please explain what needs to be done to get two char*/strings to compare in the way I want. I am open to fully rewriting my functions I just need to get this implemented.

If 4 character hard coded "password" is fine, String objects are too much overhead, IMO.
Here's demo code with a 3x4 keypad and a 16x2 display via I2C:
#include <LCD_I2C.h>
LCD_I2C lcd(0x27,16,2);
#include <Keypad.h>
const uint8_t ROWS = 4;
const uint8_t COLS = 3;
char keys[ROWS][COLS] = {
{ '1', '2', '3' },
{ '4', '5', '6' },
{ '7', '8', '9' },
{ '*', '0', '#' }
};
uint8_t colPins[COLS] = { 4, 3, 2 };
// Pins connected to C1, C2, C3
uint8_t rowPins[ROWS] = { 8, 7, 6, 5 };
// Pins connected to R1, R2, R3, R4
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
const byte OFFS =4; // position on lcd
byte pos=0; // 0...3
void setup() {
lcd.begin();
lcd.setCursor(0,1);
lcd.print("PWD:");
Serial.begin(9600);
Serial.println("keypad with lcd");
}
char pwd[5]; // 4 digits + '\0'
bool check (const char* pwd) {
return (strcmp(pwd, "1234")==0);
}
void loop() {
char key = keypad.getKey();
if (key != NO_KEY) {
// Serial.println(key);
lcd.write(key);
if (pos < 4) pwd[pos++] = key;
if (pos == 4) {
bool result = check(pwd);
if (result == false) {
pos = 0;
lcd.setCursor(0,0);
lcd.print("Wrong pwd");
lcd.setCursor(0,1);
lcd.print("PWD: ");
lcd.setCursor(OFFS,1);
} else if (pos == 4) {
lcd.setCursor(0,0);
lcd.print("Hooray ");
lcd.setCursor(0,1);
pos++;
} // else continue writing to bottom line
}
}
}

Related

How to pause my console on the desired key

I want to pause my program on the 0x32, 0x33 and 0x34 key and make it work again on the 0x31 key, how can I? I used this code to pause on the 0x32 key, it's working, but I can't get it back to work on the desired key
To summarize what #user4581301 suggested:
#include <conio.h>
...
if (GetAsyncKeyState(0x32) || GetAsyncKeyState(0x33) || GetAsyncKeyState(0x34)) {
while (_getch() != 0x31)
;
}
If your application is a console application, I implemented the function you want through loop. If it's a desktop application, you can refer to my code logic.
#include <iostream>
#include<cstdlib>
#include<time.h>
#include<Windows.h>
#include<conio.h>
using namespace std;
int main()
{
while (true) {
for (int i = 0; i < 5; ++i) {
if (GetAsyncKeyState(gun_keys[i]) && (gun != guns[i])) {
gun = guns[i];
system("cls");
gun_delay = GetTime(gun->rpm);
gun_index = 0;
break;
}
}
if (GetAsyncKeyState(VK_DELETE)) //Bind key, what close this program
{
ExitProcess(-1); //Exit Process
}
if (GetAsyncKeyState(MOUSEEVENTF_MOVE) < 0) {
if (!is_mouse_down) {
is_mouse_down = true;
if (gun != nullptr)
gun_index = 0;
}
if (gun != nullptr && gun_index != gun->len) {
mouse_event(MOUSEEVENTF_MOVE, long(gun->pattner[gun_index][0] * K), long(gun->pattner[gun_index][1] * K), 0, 0);
++gun_index;
Sleep(gun_delay);
continue;
}
}
else
is_mouse_down = false;
if (_kbhit())//Checks if there is currently keyboard input and returns a non-zero value if there is, or 0 otherwise
{
int ch = _getch();
if (ch == 0x32 || ch == 0x33 || ch == 0x34)
{
ch = _getch();//It waits for input and pauses the program
}
if (ch != 0x31)
{
while (true)
{
if (_kbhit())
{
int ch = _getch();
if (ch == 0x31) break;
}
}
}
fflush(stdin);//Clear the input buffer
}
Sleep(150);
}
return 0;
}

(Arduino) Can I skip multiple characters in a parseInt()?

Pretty much what the title says. From the arduino website:
Syntax
Serial.parseInt()
Serial.parseInt(char skipChar)
Parameters
skipChar: used to skip the indicated char in the search. Used for example to skip thousands divider.
Am I able to use a charmap or something similar to skip multiple characters?
Maybe you could read from Serial, but take digits only? And then parse string? Dirty example:
val = 0;
while (Serial.available() > 0) {
int c = Serial.read();
if (isDigit(c)) {
val = val * 10 + c; // Thanks to #Danny_ds for this
}
}
// Print *val*
I ended up using a very different method to get it working by using char arrays and not relying on timing. So far it has worked perfectly. I was using this to get my arduino to work as a temp monitor.
How it communicates the temperatures
PC > OpenHardwaremonitor > WMI > Batch Script (shown below) > COM Port > Arduino > LCD
This was the only way that I could get cpu temps correctly because it's so old
Batch code:
#echo off
mode COM3: baud=9600 data=8 >nul
wmic /namespace:\\root\openhardwaremonitor path sensor where "Identifier='/intelcpu/0/temperature/0' or Identifier='/nvidiagpu/0/temperature/0'" get Value /every:2|findstr [0-9]>COM3
Arduino code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
bool sounded = false;
int cpu = 0;
int gpu = 0;
char invalids[3] = {10, 32, '\0'}; // line feed, space
boolean newData = false;
const byte numChars = 8;
char charMap[numChars];
char tempChars[numChars];
void setup() {
pinMode(6, OUTPUT); // character intensity
pinMode(8, OUTPUT); // buzzer
pinMode(10, OUTPUT); // backlight
lcd.begin(16, 2);
Serial.begin(9600);
analogWrite(6, 100); // set intensity without POT
analogWrite(10, 168); // ~3.3v
analogReference(EXTERNAL);
lcd.print("CPU: ");
lcd.print((char)223);
lcd.print("C AIR:");
lcd.setCursor(0, 1);
lcd.print("GPU: ");
lcd.print((char)223);
lcd.print("C ");
lcd.print((char)223);
lcd.print("F");
}
void loop() {
recvWithoutWhitespace();
if (newData == true) {
parseData();
lcd.setCursor(4, 0);
lcd.print(cpu);
lcd.setCursor(4, 1);
lcd.print(gpu);
int reading = analogRead(A0);
float degreesF = (((reading * 3.3 / 1024 - 0.5) * 100) * 1.8) + 32.0;
lcd.setCursor(11, 1);
lcd.print((int)(degreesF+0.5));
if(!sounded && (cpu > 75 || gpu > 85)) { // used for buzzer alarm
tone(8, 500);
delay(250);
noTone(8);
delay(250);
tone(8, 500);
delay(250);
noTone(8);
delay(250);
tone(8, 500);
delay(250);
noTone(8);
sounded = true;
} else if(sounded && (cpu <= 75 && gpu <= 85)) {
sounded = false;
}
newData = false;
}
}
void recvWithoutWhitespace() {
static byte ndx = 0;
static byte control = 0; // switch control variable
char endMarker = 13; // ASCII code for carriage return
char rc;
char * check;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
check=strchr(invalids,rc); //checks if any spaces or line feeds get in
if (check==NULL){
if (rc != endMarker) {
charMap[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
switch(control) { // expect 4 CRs in format: (num)CRCR(num)CRCR
case 0:
control = 1; // skip first of 2 CRs
break;
case 1:
charMap[ndx] = 44; // put comma in place of CR between numbers as delimeter
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
control = 2;
break;
case 2:
control = 3; // skip first of 2 CRs
break;
case 3:
charMap[ndx] = '\0'; // string terminator in place of last CR
ndx = 0;
control = 0;
newData = true;
break;
}
}
}
}
}
void parseData() {
strcpy(tempChars, charMap); //strtok is destructive so copy string temporarily
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars, ",");
cpu = atoi(strtokIndx); // convert cpu to an integer
strtokIndx = strtok(NULL, ",");
gpu = atoi(strtokIndx); // convert gpu to an integer
}

Arduino Serial parsing

I'm working on an Arduino sketch and I'm trying to change a variable with serial. I'm using some example code that I found on arduino.cc to start with. I'm trying to modify the code with an "if statement" to update a variable timevar with integerFromPC; the problem I'm having is if I type a number higher than 4 digits like 99999 it prints out the wrong data and the variable timevar doesn't get updated correctly? I'm not sure what to do?
unsigned long timevar = 1000000;
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
// variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
int ifpc = 0;
float floatFromPC = 0.0;
boolean newData = false;
//============
void setup() {
Serial.begin(9600);
Serial.println("This demo expects 3 pieces of data - text, an integer and a floating point value");
Serial.println("Enter data in this style <HelloWorld, 12, 24.7> ");
Serial.println();
}
//============
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
showParsedData();
newData = false;
}
}
//============
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//============
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars,","); // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
integerFromPC = atoi(strtokIndx);
strtokIndx = strtok(NULL, ",");
floatFromPC = atof(strtokIndx); // convert this part to a float
}
//============
void showParsedData() {
if (strcmp(messageFromPC, "set time") == 0)
timevar = integerFromPC;
Serial.print("Time Set To ");
Serial.println(integerFromPC);
Serial.println(timevar);
}
//do other stuff
You declare int integerFromPC. int on Arduino is 16 bits. 99999 doesn't fit into 16 bits, so will appear mod 2^16 as 34463. Use long instead as you do for timeVar and it will be ok for up to +/- 2^31 .

Keypad 4*4 with Arduino

I am using keypad 4*4 with an Arduino Mega, I have sensors connected to the Arduino I want to press a key from the keypad and have response in the same time, I don't want to wait till the loop continue, I want to save up to 10 numbers entered from the keypad, so is there a way to make the keypad as an interrupt for my code?
void loop()
{
char key = kpd.getKey();
if (key != NO_KEY) {
if (key == 'C') //clear the array
{
index = 0;
numbers[index] = '\0';
}
else if (key == '.') {
numbers[index++] = '.';
numbers[index] = '\0';
}
else if (key >= '0' && key <= '9') {
for (int z = 0; z == 10; z++) {
numbers[index++] = key;
numbers[index] = '\0';
}
}
else if (key == 'A') {
float len = atof(numbers); //conversion from string to numeric
if (fona.callPhone(numbers)) {
Serial.println(F("RING!"));
Serial.print(F("Phone Number: "));
Serial.println(numbers); //print out on serial monitor
}
}
else if (key == 'D') {
if (fona.pickUp()) {
Serial.println(F("Failed"));
}
}
else if (key == '#') {
if (fona.hangUp()) {
Serial.println(F("Failed"));
}
}
}
gas = analogRead(gasPin);
dtostrf(gas, 4, 2, gass);
Serial.println(gas);
delay(1000); // Print value every 1 sec.
val = digitalRead(inputPin); // read input value
if (val == HIGH) { // check if the input is HIGH
digitalWrite(ledPin, HIGH); // turn LED ON
delay(150);
if (pirState == LOW) {
// we have just turned on
Serial.println("Motion detected!");
// We only want to print on the output change, not state
pirState = HIGH;
}
}
else {
digitalWrite(ledPin, LOW); // turn LED OFF
delay(300);
if (pirState == HIGH) {
// we have just turned off
Serial.println("Motion ended!");
// We only want to print on the output change, not state
pirState = LOW;
}
}
int ldrStatus = analogRead(ldrPin);
if (ldrStatus <= 550) {
digitalWrite(led, HIGH);
Serial.println("LDR is DARK, LED is ON");
}
else {
digitalWrite(led, LOW);
}
valee = analogRead(tempPin);
float cel = (valee * 0.48828125) / 2.12304;
dtostrf(cel, 4, 2, temp);
Serial.print("TEMPRATURE = ");
Serial.print(cel);
Serial.print("*C");
Serial.println();
delay(1000);

How to store numbers in Arduino?

I have written this to an Arduino.
char incomingbytea;
char incomingbyteb;
char incomingop;
char result;
void setup()
{
Serial.begin(9600);
}
void loop(){
incomingbytea = 0;
incomingbyteb = 0;
incomingop = 0;
result = 0;
bytea:
if (Serial.available() > 0) {
incomingbytea = Serial.read();
Serial.println("1ok");
Serial.println(incomingbytea);
goto byteb;
}
goto bytea;
byteb:
if (Serial.available() > 0) {
incomingbyteb = Serial.read();
Serial.println("2ok");
Serial.println(incomingbyteb);
goto op;
}
goto byteb;
op:
if (Serial.available() > 0) {
incomingop = Serial.read();
Serial.println("opok");
Serial.println(incomingop);
goto oper;
}
goto op;
oper:
result = incomingbytea + incomingbyteb;
Serial.println(result);
Serial.println(incomingbytea);
Serial.println(incomingbyteb);
Serial.println(incomingop);
}
What I want to do is:
- connect to serial (check)
- collect 2 variables to add/subtract/multiply/divide later (check)
- collect a variable to decide what to do with them 1-add, 2-subtract, etc. (check)
- redirect the script to do the required operation (later)
- print the result to serial (check)
The problem is, when I enter 1 and 1 and 1(whatever, the third one doesn't count now) and I get 98 as a result. Any help? Maybe the variables are wrong?
First you should know the length of the number, and subtract 48 (48 is the ascii representation of 0) later multiply the number for 1, 10, 100, 1000, 10000, ... depending of the position of each number.
For example: String "233" to integer, using custom method
void setup() {
Serial.begin(9600);
}
void loop() {
String Numero1 = "40";
String Numero2 = "50";
double Suma = StringAInt(Numero1)+StringAInt(Numero2);//+ StringAInt(Numero2);
Serial.println(Suma);
}
double StringAInt(String Dato)
{
String Numero = Dato;
char Valores [Numero.length()+1];
Numero.toCharArray(Valores,Numero.length()+1);
double NumeroEnt = 0;
for(int i = 0; i<Numero.length(); i++)
{
int NumValores = Valores[i];
NumValores-=48;
double MultPor = pow(10,Numero.length()-(i+1));
NumeroEnt += (NumValores*MultPor);
//Serial.println(NumValores*MultPor);
}
return NumeroEnt;
}
Now you only need build a string with the data received from serial port, and you can do math simply.