Pass string to class and save to eeprom - c++

I'm writing a class to save data to the EEPROM of an Arduino.
The class is called Memory.
The class contains different functions and variabeles.
char serverdefault[15] = "0032484716340";
int pricedefault = 30;
void Memory::FactoryReset()
{
TotalSold = 0;
TotalCash = 0;
Sold = 0;
Cash = 0;
Items = 0;
EEPROM_writeAnything(10, TotalSold);
EEPROM_writeAnything(20, TotalCash);
EEPROM_writeAnything(30, Sold);
EEPROM_writeAnything(40, Cash);
EEPROM_writeAnything(50, pricedefault);
EEPROM_writeAnything(60, Items);
EEPROM_writeAnything(70, serverdefault);
ReadAll();
}
Annother function allows to change the default server number.
void Memory::ChangeServer(char *number_str)
{
EEPROM_writeAnything(70, number_str);
ReadAll();
}
This function doesn't work.
I call the function in the void setup().
void setup()
{
Serial.begin(9600);
Serial.println("started");
Serial.println("factory reset");
mem.FactoryReset();
Serial.println("change server number");
mem.ChangeServer("1234567890123");
}
The value saved in the EEPROM is replaced by "b32484716340" instead of "1234567890123". What am i doing wrong?

In Memory::ChangeServer you are writing the pointer itself to EEPROM (i.e. the address), rather than the string that the pointer points to. One way to fix this would be:
void Memory::ChangeServer(char *number_str)
{
for (int i = 0; i <= strlen(number_str); ++i)
{
EEPROM_writeAnything(70 + i, number_str[i]);
}
ReadAll();
}

Related

Arrays with unknown size on Arduino

I'm doing an Arduino project and I need to pass arrays with different sizes as parameter to my function.
The problem is that std::vector is not an option.
How can I do that?
The fallback is to pass a pointer to the first element in the array and the size:
void foo(int* arr, size_t size);
The reason for std::vector not being available on some platforms is that on some platforms dynamic allocations is a bad idea. However, once you are dynamically allocating arrays:
int* x = new int[42];
foo(arr,42); // array decays to pointer
delete[] x;
then you could as well use std::vector.
If std::vector is not available to you, then either search for an alternative (maybe this?) or write your own. The pointer + size approach is fragile and not recommended unless absolutely necessary. The power of std::vector is from the abstract concept to encapsulate the array, its size and capacity. Nobody can prevent you to apply that concept even if you cannot use std::vector.
In case you are talking about statically sized arrays, then thats not quite the use case for std::vector. You do not need dynamic allocation, and you can pass arrays by reference. I won't repeat here what you can find in this answer (std::array) or here (c-arrays).
Something like this should work
template<size_t N>
void DaFunction(std::array<int, N>& daArray)
you can do it without having to deal with memory allocation or pointers just by creating a string variable and a limited size array and then you start shifting
#include <Arduino.h>
class ArrayShifter
{
private:
// String Reservoire Tank
String _text;
// a fixed size array of 5 in my case (depending on the amount of data you expect)
String _viewPortArray[5];
int _size = 0;
// Methode to fill the array
bool shiftArray(int position);
public:
ArrayShifter(/* args */);
// Method that gets the text from Serial
String getSerialText();
// get data from the array
String getArrayData(int index);
// array size getter
int getSize();
//clear the array
void clearArray();
//remove item
void removeArrayItem(int index);
};
ArrayShifter::ArrayShifter(/* args */)
{
}
String ArrayShifter::getSerialText()
{
// lesteing to the serial and returning the value
_text = Serial.readString();
return _text;
}
bool ArrayShifter::shiftArray(int position)
{
/*Assuming that the data is comming separated with ";" for each row and ":" for each value
to optimize the size of array in this way :
name:value;age:value;gender:value;
*/
String text = getSerialText();
int index = 0;
_size = 0;
if (text.length() > 0) // text isn't empty
{
if (position <= 5) // if the data belongs to the first 5 range
{
for (int i = 0; i < 5; i++)
{
// get the index of our separator that we've chosed to be ";"
index = text.indexOf(";");
if (index > 0)
{
// index found
_size++;
// putting the value before ";" in the array
_viewPortArray[i] = text.substring(0, index);
// deleting the value from the tank
text = text.substring(index + 1);
}
}
}
else
{
_size = 0;
// to wich range the desired index belongs
unsigned int dataRange = ((position - position % 5));
int ghostIndex = 0;
// looping throught all ";" to get indexes
for (int i = 0; i < dataRange; i++)
{
ghostIndex = text.indexOf(";");
if (ghostIndex > 0)
{
_size++;
text = text.substring(ghostIndex + 1);
}
}
// grabing just 5 of the data
for (int i = 0; i < 5; i++)
{
if (ghostIndex > 0)
{
_size++;
_viewPortArray[i] = text.substring(0, ghostIndex);
text = text.substring(ghostIndex + 1);
}
// updating ghost index
ghostIndex = text.indexOf(';');
}
}
return true;
}
return false;
}
String ArrayShifter::getArrayData(int index)
{
// turn the roulette
if (shiftArray(index))
{
if (index <= 5)
{
// yes we have this
return _viewPortArray[index];
}
else
{
// but we have to put it in the range of 5
index = index - 5;
return _viewPortArray[index];
}
}
}
int ArrayShifter::getSize()
{
return _size;
}
void ArrayShifter::clearArray()
{
for(int i = 0 ; i <5 ; i ++)
{
_viewPortArray->remove(i);
_size = 0;
}
}
void ArrayShifter::removeArrayItem(int index)
{
_viewPortArray->remove(index);
_size--;
}
main class :
#include <Arduino.h>
#include <ArrayShifter.h>
ArrayShifter array;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while (!Serial){}
}
void loop() {
if(Serial.available()>0)
{
Serial.println(array.getArrayData(7));
int sizeOption2 = array.getSize();
Serial.println(sizeOption2);
array.removeArrayItem(7);
Serial.println(array.getArrayData(7));
}
}
please check my github repository
https://github.com/Riadam/ViewPort-Array-Shifter-for-Arduino-Uno.git

Pass Pointer to function or array to function

I am trying to figure out what I am doing wrong. I have the problem down to a few lines of code. The program will freeze or behave incorrectly when code is used.
Just wondering if I am passing this correctly for the array's?
void callFunction(uint8_t &channel)
{
uint8_t address[8]; //1wire wire address and CRC
uint8_t scratchPad[8]; //holding for onewire capture
readScratchPad(address,scratchPad,channel);
}
void Temperature::readScratchPad(uint8_t rom[8],uint8_t data[8],const uint8_t &channel)
{
//read temperature data.
wireReset(); //reset();
selectChannel(channel); //necessary on -800
wireSelect(rom);
wireWriteByte(0xbe); // Read Scratchpad command
//display hex values of scratchpad
for ( int i = 0; i < 8; i++) { // we need 9 bytes
data[i] = wireReadByte();
}
}
The only other thing it could be is that I am passing a pointer to a function incorrectly like this:
function getNext()
{
uint8_t address[8];
getNextAddress(address);
}
bool Temperature::getNextAddress(uint8_t *vAddress)
{
if ( !wireSearch(vAddress))
{
wireResetSearch();
wireReset();
wireSkip();
return false;
}
return true;
}
I was passing the pointer as getNext(&address[8]), but it did not work either.
Thanks,

c++ int member changes on its own

I am new to c++.
It looks like member variable _scheduleSize gets value kind of "integer_half_max" without any reason. Could someone please explain me why is this happening?
Invocation
leds.addSchedulePoint(new ScheduledLedPoint(ScheduleTime(9), 0));
of method:
void ScheduledLeds::addSchedulePoint(ScheduledLedPoint *schedulePoint) {
Serial.print("_scheduleSize:");
Serial.println(_scheduleSize);
_schedule[_scheduleSize++] = schedulePoint;
Serial.print("_scheduleSize:");
Serial.println(_scheduleSize);
for (size_t i = 0; i < _scheduleSize; i++) {
Serial.println(_schedule[i]->getLevel());
}
}
results in such console output :
_scheduleSize:0
_scheduleSize:1073680860
0
Exception (28):
epc1=0x40206514 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000010 depc=0x00000000
Below you can see entire class:
class ScheduledLeds {
public:
ScheduledLeds(int pin);
void addSchedulePoint(ScheduledLedPoint *schedulePoint);
void process(ScheduleTime currentTime);
void freezeLedLevel(int targetLevel, int minutes);
int _pin;
private:
ScheduledLedPoint *_schedule[];
int _scheduleSize;
int _count;
int _size;
long _unfreezeTime;
int _lastLevel;
ScheduleTime _lastTime;
void setTransitionalLightLevel(ScheduleTime now, ScheduledLedPoint nextPoint);
void setLightLevel(int targetLevel);
};
ScheduledLeds::ScheduledLeds(int pin) {
pinMode(pin, OUTPUT);
_pin = pin;
_scheduleSize = 0;
_size = 10;
_unfreezeTime = millis();
ScheduledLedPoint *_schedule[_size];
}
void ScheduledLeds::addSchedulePoint(ScheduledLedPoint *schedulePoint) {
Serial.print("_scheduleSize:");
Serial.println(_scheduleSize);
_schedule[_scheduleSize++] = schedulePoint;
Serial.print("_scheduleSize:");
Serial.println(_scheduleSize);
for (size_t i = 0; i < _scheduleSize; i++) {
Serial.println(_schedule[i]->getLevel());
}
}
ScheduledLedPoint *_schedule[]; is not valid C++ and shouldn't compile. Some compilers accept it as an extension - but even there, it's an array of zero size; _schedule[x] exhibits undefined behavior for any value of x.
When you write ScheduledLedPoint *_schedule[_size] in the constructor, that doesn't affect the data member named _schedule, as you seem to believe. Instead, it creates and immediately destroys a local variable that also happens to be named _schedule; this has exactly zero net effect.
For an array-like data structure of variable size, use std::vector.
because you have syntax error including this recursive function

Return array or multiple variables from a function

int arrays[2] = {0,1};
void setup () {
Serial.begin(9600);
pinMode(2,INPUT);
}
void loop () {
int buttonstate = digitalRead(2); //reads I/O pin 2
if (buttonstate==HIGH) { //if I/O pin 2 is HIGH do following
arrays[] = function(arrays); //calls function "function"
Serial.println(arrays[0]); //prints out arrays[0]
Serial.println(arrays[1]); //prints out arrays[1]
}
}
int function (int arrays [2]) {
int holder = arrays[1]; //switches place the values on the array
arrays[1] = arrays[0];
arrays[0] = holder;
return arrays[]; //return the modified array
}
What am I doing wrong here? Can someone explain why my code is wrong?
Why doesn't it just return the array and modify its content? I have read on other articles about pointers, but I couldn't understand how they worked.
Well, your worst misconception is thinking that C allows you to pass a complete array as parameter or return value.
First of all, you cannot do an assignment like
arrays[] = function(...);
This is incorrect, as there's no way to refer to the array as a whole. You can return a reference to an array, something like:
arrays = function(...);
always that your function returns a valid POINTER TO INTEGER, and always that you declare your arrays variable as int *arrays;, instead. But this has another problem... a pointer doesn't allocate memory for the pointed to values.
The best solution is to use the array reference to pass it to the function, and then make the function to operate on the array proper. Like in
function(arrays); /* you should have function exchanged the arrays values properly */
for (i = 0; i < 2; i++) /* print arrays contents and check values have been exchanged */
printf("arrays[%d] == %d\n", i, arrays[i]);
in this case, the arrays() function should have been implemented as
void function(int arrays[])
{
int temporary = arrays[0];
arrays[0] = arrays[1];
arrays[1] = temporary;
/* no return as function is declared void */
}
Of course, you can return the reference to the original array, and this can be helpful in some expressions, but think always that you are dealing with the same array anycase.
int *function(int *arrays) /* this parameter declaration is equivalent to the last one */
{
int temporary = arrays[0];
arrays[0] = arrays[1];
arrays[1] = temporary;
return arrays; /* reference to the first array element */
}
The array is passed to the function by reference.
If you modify the array in the function, the changes will persist after the function call.
int arrays[2] = {0, 1};
void setup() {
Serial.begin(9600);
pinMode(2, INPUT);
}
void loop() {
int buttonstate = digitalRead(2); //reads I/O pin 2
if (buttonstate == HIGH) { //if I/O pin 2 is HIGH do following
function(arrays); //calls function "function"
Serial.println(arrays[0]); //prints out arrays[0]
Serial.println(arrays[1]); //prints out arrays[1]
}
}
void function(int arrays[]) {
int holder = arrays[1]; //switches place the values on the array
arrays[1] = arrays[0];
arrays[0] = holder;
}
If you don't want to modify the existing array, you will need to pass another array.
int arrays[2] = {0, 1};
int arrays2[3];
void setup() {
Serial.begin(9600);
pinMode(2, INPUT);
}
void loop() {
int buttonstate = digitalRead(2); //reads I/O pin 2
if (buttonstate == HIGH) { //if I/O pin 2 is HIGH do following
function(arrays, arrays2); //calls function "function"
Serial.println(arrays2[0]); //prints out arrays2[0]
Serial.println(arrays2[1]); //prints out arrays2[1]
Serial.println(arrays2[2]); //prints out arrays2[2]
}
}
void function(int arrays[], int arrays_return[]) {
arrays_return[0] = arrays[1];
arrays_return[1] = arrays[0];
arrays_return[2] = arrays[0] + arrays[1];
}
You will need to make sure that the array have appropriate size, because there won't be any explicit error thrown if you write/read outside the array's range, but you may find some odd behavior that will be hard to debug.

How do I pass a pointer to an array of pointers as an argument to a function?

I'm trying to code a robot, and I'm having a confusing situation. I need to pass an array of pointers to objects to a constructor of a class. I can't, however, populate the array before I pass it into the constructor. To solve this I want to pass a pointer to said array, and access its elements from the pointer. The problem is that I'm new to C++, and so I'm not sure of the syntax. Could you guys help me out?
Code for the main file
class RobotDemo : public SimpleRobot
{
Joystick stick;
JoystickOne joyOne;
Victor *victors [8];
public:
RobotDemo(void):
stick(1),
joyOne(&stick)// these must be initialized in the same order
// as they are declared above.
/*It doesnt seem like I can do anything but initialize things here*/
{
/*Populate array with pointers to victors. Will need to update channels*/
for (int x = 1; x <= 7; x++) {
victors[x] = new Victor(x);
}
/*And I don't think I can initialize anything here*/
myRobot.SetExpiration(0.1);
}
/**
* Drive left & right motors for 2 seconds then stop
*/
void Autonomous(void)
{
}
/**
* Runs the motors with arcade steering.
*/
void OperatorControl(void)
{
myRobot.SetSafetyEnabled(true);
while (IsOperatorControl())
{
joyOne.testForActions(); /*Check joystick one for actions*/
Wait(0.005); // wait for a motor update time
}
}
/**
* Runs during test mode
*/
void Test() {
}
};
START_ROBOT_CLASS(RobotDemo);
Here's the code for the JoystickInput class, which the JoystickOne class extends
//the .h
#ifndef JOYSTICKINPUT_H
#define JOYSTICKINPUT_H
#include "WPILib.h"
class JoystickInput {
public:
JoystickInput(Joystick*);
JoystickInput(Joystick*, Victor* [8]);
Joystick * joystick;
bool buttons [10];
Victor** victors [8];
bool buttonClicked(int id);
virtual void testForActions();
};
#endif
//and the .cpp
#include "JoystickInput.h"
JoystickInput::JoystickInput(Joystick * joy) {
joystick = joy;
for (int x = 0; x < 10; x++) {
buttons[x] = false;
}
}
JoystickInput::JoystickInput(Joystick * joy, Victor* vicArray [8]) {
joystick = joy;
for (int x = 0; x < 10; x++) {
buttons[x] = false;
}
for (int n = 0; n <=7; n++) {
*victors[n] = vicArray[n];
}
}
bool JoystickInput::buttonClicked(int id) {
if (buttons[id] == false and joystick->GetRawButton(id) == true) {
buttons[id] = true;
return true;
} else if (buttons[id] == true and joystick->GetRawButton(id) == false) {
buttons[id] = false;
return false;
} else {
return false;
}
}
void JoystickInput::testForActions() {
}
What I'm asking you guys to help me do is rework the constructor of JoystickInput() so that it also takes a pointer to an array of pointers (to Victors), and performs methods on elements of the array. Googling it hasnt turned up anything useful. I'd research it more myself, but its been a few days and I'm still hung up on this.
Thanks for the help (and if not that, then at least reading my post)!
You should be able to use:
JoystickInput(Joystick*, Victor**, int);
and just pass vicArray into the constructor. If victors can be anything else than an array of length 8, then you should also pass the length as an argument because c++ cannot find the length of an array from a pointer.
Whenever types get complicated (functions or arrays), use a typedef:
typedef char char_buffer_type[8]; //char_buffer_type is an array
typedef char (*char_buffer_ptr)[8]; //char_buffer_ptr is a pointer to an array
typedef char (&char_buffer_ref)[8]; //char_buffer_ref is a reference to an array
typedef int main_type(int, char**); //main_type is a "int(int, char**)" function
typedef Victor*(array_of_ptr)[8]; //array_of_ptr is an array of 8 Victor*
Also, you should name the values 8 and 10.
class JoystickInput {
public:
static const int victor_count = 8;
static const int button_count = 10;
typedef Victor*(array_of_victor_ptr)[victor_count];
JoystickInput(Joystick*){}
JoystickInput(Joystick*, array_of_victor_ptr& vicArray);
bool buttonClicked(int id){return true;}
virtual void testForActions(){}
Joystick * joystick;
bool buttons [button_count];
array_of_victor_ptr victors; //that's simpler
};
//then pass this one by reference
JoystickInput::JoystickInput(Joystick * joy, array_of_victor_ptr& vicArray) {
joystick = joy;
for (int x = 0; x < button_count; x++) {
buttons[x] = false;
}
for (int n = 0; n < victor_count; n++) {
victors[n] = vicArray[n]; //don't have to dereference here anymore
}
}
Proof of compilation. Typedefs are wonderful. Use them.