Trash on Arduino serial monitor. How to fix it? - c++

i'm working with I2C eeprom and Arduino. For now i tried to create simple keyboard that will start specific functions. I want to write to serial monitor potentiometer value, but i get trash instead it. How to fix it?
My functions:
int *readPot() ///read potentiometer value
{
int tempValue = analogRead(A0);
int *potValue = &tempValue;
return potValue;
}
void keyboardProcess() ///process keyboard input
{
int *potValue = readPot();
for(int i = 0; i < 2; i++)
{
btnReadings[i] = digitalRead(keysPins[i]);
}
if(btnReadings[0] == HIGH)
{
Serial.println("Potentiometer reading:" + *potValue);
}
}

One obvious problem is that you are returning the address to a local variable:
int *readPot() ///read potentiometer value
{
int tempValue = analogRead(A0);
int *potValue = &tempValue;
return potValue;
}
Here, the returned pointer points to the address of tempValue. This ceases to be valid once the function returns. Just use an int:
int readPot() ///read potentiometer value
{
return analogRead(A0);
}
Next, I doubt that this is a valid argument to Serial.println:
Serial.println("Potentiometer reading:" + *potValue);
but this should work:
int potValue = readPot();
Serial.print("Potentiometer reading: ");
Serial.println(potValue);

Related

Read Serial Input into Char Array

So i've managed to wire up an ESP-01 module to my arduino, now im attempting to parse the +IPD responses the chip gives over a serial connection. Im not really all that handy with C++ but this is what i've managed to come up with after researching a bunch online:
#include <SoftwareSerial.h>
SoftwareSerial ESP8266(2, 3); // RX | TX
int baud = 9600;
void setup() {
ESP8266.begin(baud);
Serial.begin(baud);
Serial.println("--- Start ---");
}
void loop() {
if (ESP8266.available()) // check if the esp is sending a message
{
Serial.println("Something received");
delay(500);
if (ESP8266.find("%<"))
{
Serial.println("--------------- DEBUG ----------------A");
char temp = {char(ESP8266.read())};
while ((temp != '%') && (ESP8266.available())) {
Serial.print(temp);
temp = char(ESP8266.read());
}
Serial.println("\n--------------- END DEBUG ----------------");
}
}
}
The standard response the chip gives when receiving a message is as follows:
+IPD,<len>:<Message>
+IPD,0,14:%<255,128,0%
The data im trying to send - random RGB values (using '%<' and '%' as flags/markers):
%<255,128,0%
From here, i've managed to write the above code, which will print out the following over serial:
So i've managed to get it to print the values i need over Serial, but i cant seem to store them in an array of some sort to do things with the data.
Things i've tried:
using readString() instead of read(), coupled with indexOf to search/extract the data
Looping and appending to a char array
A bunch of array stuff, seems tricky though because you have to know the length when you declare it
Ideally, i'd like a function that reads the +IPD value, extracts the RGB data and then splits it into a 3 index array, like so:
rgbArray = {124, 234, 96};
Any and all help is super appreciated!
To store the input to an array, just allocate an array and store the data there.
Serial.println("--------------- DEBUG ----------------A");
int receivedLength = 0;
char data[16];
char temp = ESP8266.available();
while ((temp != '%') && (ESP8266.available())) {
Serial.print(temp);
if (receivedLength < 16) data[receivedLength++] = temp;
}
for (int i = 0; i < receivedLength; i++) Serial.print(data[i]);
Serial.println("\n--------------- END DEBUG ----------------");
Alternatively, you can do conversion to integers while reading like this:
Serial.println("--------------- DEBUG ----------------A");
int rgbSize = 0;
int rgbArray[3];
int currentValue = 0;
char temp = ESP8266.available();
while ((temp != '%') && (ESP8266.available())) {
Serial.print(temp);
if (temp == ',') {
if (rgbSize < 3) rgbArray[rgbSize++] = currentValue;
currentValue = 0;
} else {
currentValue = currentValue * 10 + (temp - '0');
}
}
if (rgbSize < 3) rgbArray[rgbSize++] = currentValue;
for (int i = 0; i < rgbSize; i++) {
if (i > 0) Serial.print(',');
Serial.print(rgbArray[i]);
}
Serial.println("\n--------------- END DEBUG ----------------");
Ended up going with a different way of doing things:
Managed to read about readStringUntil(''); in some dark corner of the web. So i came up with a super dirty implementation - but it works:
Assume your input string is:
+IPD,0,14:%<255,128,0%
Then do:
if (ESP8266.available()) // check if the esp is sending a message
{
delay(500);
if (ESP8266.find("%<"))
{
r = ESP8266.readStringUntil(',');
g = ESP8266.readStringUntil(',');
b = ESP8266.readStringUntil('%');
}
}

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,

Modifying integer value from another process using process_vm_readv

I am using Ubuntu Linux to write two programs. I am attempting to change the value of an integer from another process. My first process (A) is a simple program that loops forever and displays the value to the screen. This program works as intended and simply displays the value -1430532899 (0xAABBCCDD) to the screen.
#include <stdio.h>
int main()
{
//The needle that I am looking for to change from another process
int x = 0xAABBCCDD;
//Loop forever printing out the value of x
int counter = 0;
while(1==1)
{
while(counter<100000000)
{
counter++;
}
counter = 0;
printf("%d",x);
fflush(stdout);
}
return 0;
}
In a separate terminal, I use the ps -e command to list the processes and note the process id for process (A). Next as root use (sudo) I run this next program (B) and enter in the process ID that I noted from process (A).
The program basically searches for the needle which is in memory backwards (DD CC BB AA) find the needle, and takes note of the address. It then goes and tries to write the hex value (0xEEEEEEEE) to that same location, but I get a bad address error when errno is set to 14. The strange thing is a little later in the address space, I am able to write the values successfully to the address (0x601000) but the address where the needle(0xAABBCCDD) is at 0x6005DF I cannot write there. (But can read obviously because that is where I found the needle)
#include <stdio.h>
#include <iostream>
#include <sys/uio.h>
#include <string>
#include <errno.h>
#include <vector>
using namespace std;
char getHex(char value);
string printHex(unsigned char* buffer, int length);
int getProcessId();
int main()
{
//Get the process ID of the process we want to read and write
int pid = getProcessId();
//Lists of addresses where we find our needle 0xAABBCCDD and the addresses where we simply cannot read
vector<long> needleAddresses;
vector<long> unableToReadAddresses;
unsigned char buf1[1000]; //buffer used to store memory values read from other process
//Number of bytes read, also is -1 if an error has occurred
ssize_t nread;
//Structures used in the process_vm_readv system call
struct iovec local[1];
struct iovec remote[1];
local[0].iov_base = buf1;
local[0].iov_len = 1000;
remote[0].iov_base = (void * ) 0x00000; //start at address 0 and work up
remote[0].iov_len = 1000;
for(int i=0;i<10000;i++)
{
nread = process_vm_readv(pid, local, 1, remote, 1 ,0);
if(nread == -1)
{
//errno is 14 then the problem is "bad address"
if(errno == 14)
unableToReadAddresses.push_back((long)remote[0].iov_base);
}
else
{
cout<<printHex(buf1,local[0].iov_len);
for(int j=0;j<1000-3;j++)
{
if(buf1[j] == 0xDD && buf1[j+1] == 0xCC && buf1[j+2] == 0xBB && buf1[j+3] == 0xAA)
{
needleAddresses.push_back((long)(remote[0].iov_base+j));
}
}
}
remote[0].iov_base += 1000;
}
cout<<"Addresses found at...";
for(int i=0;i<needleAddresses.size();i++)
{
cout<<needleAddresses[i]<<endl;
}
//How many bytes written
int nwrite = 0;
struct iovec local2[1];
struct iovec remote2[1];
unsigned char data[] = {0xEE,0xEE,0xEE,0xEE};
local2[0].iov_base = data;
local2[0].iov_len = 4;
remote2[0].iov_base = (void*)0x601000;
remote2[0].iov_len = 4;
for(int i=0;i<needleAddresses.size();i++)
{
cout<<"Attempting to write "<<printHex(data,4)<<" to address "<<needleAddresses[i]<<endl;
remote2[0].iov_base = (void*)needleAddresses[i];
nwrite = process_vm_writev(pid,local2,1,remote2,1,0);
if(nwrite == -1)
{
cout<<"Error writing to "<<needleAddresses[i]<<endl;
}
else
{
cout<<"Successfully wrote data";
}
}
//For some reason THIS will work
remote2[0].iov_base = (void*)0x601000;
nwrite = process_vm_writev(pid,local2,1,remote2,1,0);
cout<<"Wrote "<<nwrite<<" Bytes to the address "<<0x601000 <<" "<<errno;
return 0;
}
string printHex(unsigned char* buffer, int length)
{
string retval;
char temp;
for(int i=0;i<length;i++)
{
temp = buffer[i];
temp = temp>>4;
temp = temp & 0x0F;
retval += getHex(temp);
temp = buffer[i];
temp = temp & 0x0F;
retval += getHex(temp);
retval += ' ';
}
return retval;
}
char getHex(char value)
{
if(value < 10)
{
return value+'0';
}
else
{
value = value - 10;
return value+'A';
}
}
int getProcessId()
{
int data = 0;
printf("Please enter the process id...");
scanf("%d",&data);
return data;
}
Bottom line is that I cannot modify the repeating printed integer from another process.
I can see at least these problems.
No one guarantees there's 0xAABBCCDD anywhere in the writable memory of the process. The compiler can optimize it away entirely, or put in in a register. One way to enssure a variable will be placed in the main memory is to declare it volatile.
volatile int x = 0xAABBCCDDEE;
No one guarantees there's no 0xAABBCCDD somewhere in the read-only memory of the process. On the contrary, one could be quite certain there is in fact such a value there. Where else could the program possibly obtain it to initialise the variable? The initialisation probably translates to an assembly instruction similar to this
mov eax, 0xAABBCCDD
which, unsurprisingly, contains a bit pattern that matches 0xAABBCCDD. The address 0x6005DF could well be in the .text section. It is extremely unlikely it is on the stack, because stack addresses are typically close to the top of the address space.
The address space of a 64-bit process is huge. There is no hope to traverse it all in a reasonable amount of time. One needs to limit the range of addresses somehow.

arduino if statement giving error

I am working on some arduino code and my program keeps on giving me this error,
ISO C++ forbids comparison between pointer and integer [-fpermissive]
I've tried searching on the internet to solve this issue but, either the solution is incorrect, or irrelevant. here is where the arduino software is saying the problem is,
if((millis - incLastDebounce) > debounceDelay) {
and if you need the rest of the code here it is,
#include <LiquidCrystal.h>
int freq = 0;
int change = 0;
const int incPin = 3;
const int setPin = 2;
int incButtonState;
int setButtonState;
int incPreviousState;
int setPreviousState;
int incLastDebounce;
int setLastDebounce;
const int debounceDelay = 50;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
// put your setup code here, to run once:
lcd.begin(16, 2);
pinMode(setPin, INPUT);
pinMode(incPin, INPUT);
lcd.print("Frequency: " + freq);
}
void loop() {
// put your main code here, to run repeatedly:
int incReading = digitalRead(incPin);
int setReading = digitalRead(setPin);
if(setReading != setPreviousState) {
setLastDebounce = millis();
}
if(incReading != incPreviousState) {
incLastDebounce = millis();
}
if((millis - setLastDebounce) > debounceDelay) {
if(setReading != setButtonState) {
setButtonState = setReading;
}
if(setButtonState == HIGH) {
//Okay so here you will do your set lcd voodoo
}
}
if((millis - incLastDebounce) > debounceDelay) {
if(incReading != buttonState) {
incButtonState = incReading;
}
if(buttonState == HIGH) {
// here you can put the lcd code
change = change + 500;
if(change == 10500){
change = 0;
}
}
}
incPreviousState = incReading;
setPreviousState = setReading;
}
hopefully you can find the problem and help.
Looks like you're missing parentheses after millis, so instead of calling the function, you're trying to do arithmetic with its memory address.
This will probably work better:
if ((millis() - incLastDebounce) > debounceDelay) {

Pass string to class and save to eeprom

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();
}