Arduino variable usage - c++

I'm a newbie when it comes to Arduino and C++.
I'm trying to write a program that reads the input data from analog pin zero (a POT).
after the value is read I want it to print to the serial monitor, but only once. if the value of from analog pin zero changes I want it to print the new value to the serial monitor. I'm trying to use global variables, but to no avail. any help would be greatly appreciated!
int entered=0;
int flag;
void setup()
{
Serial.begin(9600);
}
void loop() {
int potValue=analogRead(A0);
if (!entered){
entered=1;
Serial.println(potValue);
}
int flag=potValue;
if (flag!=flag){
entered=0;
}
}

That is really close. This line is your mistake
int flag=potValue;
As written, that creates a new local variable flag. The local variable hides the global variable. So the comparison is always to itself and never fails. Change the line to :
flag=potValue;
and your program will function as desired.
You can save some memory and code space like this:
int g_lastValue = 0;
void loop() {
int nowValue = analogRead(A0);
if (nowValue != g_lastValue) {
Serial.println(nowValue);
g_lastValue = nowValue;
}
...
}
The use of g_ as name prefix is a cue that a variable is global. I use this naming convention as it helps when reading a function to know variables that are not local. Without a name cue, you need to scan the entire function body to see if there is a variable declaration present, and only by looking through the function and not finding a declaration can you know the variable must be global. On small functions, not really an issue, but as your code grows, you may want some self documentation a naming convention provides.

You're on your way but you are getting tangled a bit in variables.
It can be simpler: just one global variable and one conditional check.
int lastRead = -1; // init to value outside of possible range
void setup()
{
Serial.begin(9600);
}
void loop() {
// get current value
int currentRead = analogRead(0);
//compare and only print if !=
if (currentRead != lastRead){
lastRead = currentRead; // store
Serial.println(lastRead);
}
}

Related

How to test a function which returns void in google test?

I have a function which needs to be tested but it returns void.
This function may modify some global variables.
For example:
/* target_code.h */
void add_num(int n);
/* target_code.c */
#include "target_code.h"
int number = 0;
void add_num(int n) {
number += n;
}
(The real function I want to test is more complex than it.)
And I want to use the framework - google test for testing this function.
So maybe I need to implement a test program to test it.
/* testProgram.cpp */
include "target_code.h"
/* implement the test case for it */
But this function doesn't return anything. It just modifies a global variable.
And in my coworker's point, it's not good to extern this variable number and check the value is correct or not in this example.
The one of the bad things is, maybe we will change the variable name about number and this test program may need to rewrite again (difficult to maintain).
But without this method, I don't know how to test this function works correctly or not.
A single method I thought is implementing a function which do the similar thing with add_num, and verifying this function.
Here is a example which I thought:
/* testProgram.cpp */
int fake_number = 0;
void fake_add_num(int n) {
fake_number += n;
}
/* Implement the test cases */
This fake_add_num do the same thing with the real function "add_num". The different between them is I can reach this fake_number directly.
Maybe there are different methods to verify this kind of functions.
Please give me an example to do that. Thanks!!
You should figure out what the observable behavior of this function is and test that. Everything else is implementation detail.
For example, if you have a companion to your add_num function:
void print_num() {
std::cout << number << '\n';
}
Then the observable behavior of add_num(2) isn't "number is increased by 2", it's "The number printed by print_num() is increased by 2". That is the behavior you should test.
For example, you could write a test like this:
TEST(NumTests, AddNumReflectedInPrintNum) {
init_num(0);
testing::internal::CaptureStdout();
print_num();
ASSERT_EQ(testing::internal::GetCapturedStdout(), "0\n";)
add_num(10);
testing::internal::CaptureStdout();
print_num();
ASSERT_EQ(testing::internal::GetCapturedStdout(), "10\n";)
}
Note that the value of number is never tested anywhere. That is an implementation detail.
You can make an internal visible method (in some internal namespace) that tests uses it to get this global state and then you can do something like
// in header
namespace my_proj {
namespace internal {
int GetNumber() { return number; }
}
}
// in test
add_num(5);
EXPECT_EQ(expected_value, GetNumber());
One last thing, using global variables is not a recommended approach because of the issues it can introduce, so if you can avoid it, might be better.

In C++, coding for Arduino, how can I save a function to a variable and call it later via the variable?

I want to save a function I've made to a string variable and call it later via the variable - something like this:
String hello = "helloWorld();";
void loop()
{
hello;
}
void helloWorld()
{
//does functional things...
}
This is a super basic idea of what I want to make happen.
I'm making a game and want a certain function (different every time) to be stored in a variable to be played back later.
To declare a function pointer, you need to know its signature.
If your function helloWorld does not take parameters and returns nothing (void
), a variable to store that could be defined as
void (*myFunc)() = helloWorld;
void loop()
{
myFunc();
}
The only Arduino specific is that usually the required function declaration is done for you secretly behind the scenes.

Arduino - Enum variable value change by itself

I created an Arduino mega sketch to control LEDs channel to simulate simple sunset and sunrize. In my class LEDChannel declaration, i have an public enum to represent the state of the LED Channel and i have a private instance (CurrentState) of State enum in the class to keep track of this LEDChannel instance.
Everything compile well and is uploaded to my Arduino Mega. The problem is when i debug my code and check the value of CurrentState variable i get a value outside of enum range. Sometime i get value 7579 (actual value in my last test). Another day i can get a value of 612. The value should only be 0 to 4. I verified my code and any place i change the value of this variable, i use the enum. By example :
CurrentState = ManualSunset;
CurrentState variable receive the value NoAction in the default constructor of LEDChannel Class.
The class LEDChannel is part of a bigger project to make an Aquarium controller with other class to represent RTC time module, Bluetooth module, Fan and temperature sensor.
I developed my project with Visual Studio Community 2015 with vMicro plugin for Arduino. If you need the complete project, i will find a way to make it available.
Here is the LEDChannel Declaration/definition and main Arduino program .ino. This is a light version of my code. I removed all unnecessary code. To reproduce the problem, just comment line 13 in main program nNbLEDChannel = 1;. You should then get value ManualSunrise (3) for variable CurrentState. Take not that nNbLEDChannel is only used in main .ino file.
#pragma once
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
//#include "DataTypes.h"
typedef byte duration;
class AquariumSimulator;
class LEDChannel
{
public:
typedef enum State
{
AutomaticSunset = 0,
AutomaticSunrise = 1,
ManualSunset = 2,
ManualSunrise = 3,
NoAction = 4
};
private:
byte MaxBrightness;
unsigned long lastTick;
byte CurrentBrightness;
LEDChannel::State CurrentState;
byte DigitalPin;
duration ManualSunsetDuration;// In secondes
duration ManualSunriseDuration;// In secondes
AquariumSimulator* pAquariumSim;
public:
void StartManualSunrise(duration SecDuration);
void PerformSunrise();
LEDChannel();
LEDChannel(byte DigitalPIN, AquariumSimulator* pSim);
private:
void PerformManualSunrise();
void SetCurrentBrightness(byte value);
void IncreaseCurrentBrightness(byte value = 1);
};
Here is the LEDChannel.cpp
#include "LEDChannel.h"
/*
Constuctor
*/
LEDChannel::LEDChannel(byte DigitalPIN, AquariumSimulator* pSim)
{
LEDChannel();
// Initialize default values
pAquariumSim = pSim;
pinMode(DigitalPIN, OUTPUT);// Configure Digital pin that control LED Channel
}
LEDChannel::LEDChannel()
{
CurrentState = NoAction;
}
void LEDChannel::PerformSunrise()
{
switch (CurrentState)
{
case AutomaticSunrise:
//PerformAutomaticSunrise();
break;
case ManualSunrise:
PerformManualSunrise();
break;
}
}
void LEDChannel::PerformManualSunrise()
{
unsigned long currentTick = millis();
if (currentTick >= (lastTick + ManualSunriseDuration / MaxBrightness))
{
// If current brightness is at max brigthness value, stop sunset
if (CurrentBrightness == MaxBrightness)
{
CurrentState = NoAction;
lastTick = 0;
}
else
{
IncreaseCurrentBrightness();
lastTick = currentTick;
}
}
}
void LEDChannel::SetCurrentBrightness(byte value)
{
if (value > 255)
CurrentBrightness = 255;
else
CurrentBrightness = value;
analogWrite(DigitalPin, CurrentBrightness);
}
void LEDChannel::IncreaseCurrentBrightness(byte value)
{
if ((CurrentBrightness + value) <= 255)
CurrentBrightness += value;
else
CurrentBrightness = 255;
SetCurrentBrightness(CurrentBrightness);
}
// Manual Sunrise for a duration in secondes
void LEDChannel::StartManualSunrise(duration SecDuration)
{
switch (CurrentState)
{
case NoAction:
CurrentState = ManualSunrise;
ManualSunriseDuration = SecDuration;
SetCurrentBrightness(0);
break;
}
}
And main program .ino
#include "LEDChannel.h"
LEDChannel** pLED;
byte nNbLEDChannel;
void setup()
{
pLED = new LEDChannel*[1];
pLED[0] = new LEDChannel(44, NULL);
/* If i put the next line as comment CurrentState get a valid value.
If i assigne a value to nNbLEDChannel I get invalid value for CurrentState*/
nNbLEDChannel = 1;
pLED[0]->StartManualSunrise(10);
}
void loop()
{
pLED[0]->PerformSunrise();
}
I didn't get out my Arduino UNO board, but I am pretty sure your main problem is the fact that you are trying to call the default constructor from within another constructor. Edit: The call to LEDChannel() you did actually constructed a new instance of the class which then never gets used or assigned. The version of the C++ standard being used by default by Arduino doesn't support that feature, see the following answer for more information (It also demonstraits the correct syntax for calling a constructor from another constructor if you are using a version of the standard which supports it). This means that the CurrentState variable is uninitialized and will be some random value as you are observing. Uncommenting out the line:
nNbLEDChannel = 1;
really doesn't have anything to do with the error and just rearranges the memory which apparently happens to put the CurrentState variable to a valid value.
Similar functionality, having common code within a constructor, can be achieved by moving your common initialization code out of the default constructor and into another function like this, which is then called by both constructors (don't forget to initialize all of the member variables of the class in this function to a default value and then do any other "special" initialization after it):
LEDChannel::LEDChannel(byte DigitalPIN, AquariumSimulator* pSim)
{
// Initialize default values
commonInitFunction();
//Do other "special" initialization
pAquariumSim = pSim;
//pinMode(DigitalPIN, OUTPUT);// Configure Digital pin that control LED Channel
}
LEDChannel::LEDChannel()
{
// Initialize default values
commonInitFunction();
//Do other "special" initialization
}
void LEDChannel::commonInitFunction()
{
CurrentState = NoAction;
//make sure all other member variables have been initialized to something either in here or
//in your constructors to keep from having unexpected behavior
}
Although it is a good idea to initialize variables in an initializer list, as stated here, which would then change your constructors to be the following (Note: I just picked some random default values):
LEDChannel::LEDChannel(byte DigitalPIN, AquariumSimulator* pSim):
MaxBrightness(255),
lastTick(0),
CurrentBrightness(0),
CurrentState(NoAction),
DigitalPin(DigitalPIN),
ManualSunsetDuration(60),
ManualSunriseDuration(60),
pAquariumSim(pSim)
{
//pinMode(DigitalPIN, OUTPUT);// Configure Digital pin that control LED Channel
}
LEDChannel::LEDChannel():
MaxBrightness(255),
lastTick(0),
CurrentBrightness(0),
CurrentState(NoAction),
DigitalPin(0),
ManualSunsetDuration(60),
ManualSunriseDuration(60),
pAquariumSim(NULL)
{
CurrentState = NoAction;
}
This ensures all values are initialized (including in the proper order) for the instantiation of the class.
On a side note, I did notice a few other items in the code you provided which might cause you some unexpected behavior.
Since CurrentBrightness is a byte (i.e. uint8_t), in your void LEDChannel::IncreaseCurrentBrightness(byte value) method, your check to see if the CurrentBrightness + value is <= 255. This will only ever be false if the sum is equal to 255 because of overflow. Basically, if the CurrentBrightness is 250 and I add the value of 10 to it then I will get a value of 4 if I am not mistaken. This is probably not the desired behavior of this check.
The second is that the typedef keyword for your enum is not doing anything since you didn't specify a type. In C++, you don't need the typedef for an enumeration or struct if you only want to refer to it by the original name you gave it, like you did here. See some of the answers here, even though none of them were accepted the first few are
Have you guaranteed that loop() cannot be called before setup() ?
It is suspicious that setting a value immediately after your pointer array is the "source" of the problem. This leads me to suspect that either the pLED value is getting changed or you have some other indexing problem that is causing the memory where nNbLEDChannel resides to be interpreted as a LEDChannel object.

error: 'set' was not declared in this scope

I've already searched through this site and on Google, but I couldn't find anything helping me. I'm a total C++ noob and started coding yesterday, today I've spent couple of hours trying to figure out what I did wrong and I was already able to resolve like 10 errors (which is a lot in such a small code section, I know ._.). What did I do wrong? I do have small Java knowledge and a few scripting languages like LUA and Autoit3.
This is just a small program to test the GPIO pins on my Raspberry PI and to get used to the C++ syntax and to learn a little about programming.
Edit: The error occurrs twice, I've noted that down using comments
#include <wiringPi.h>
#include <stdio.h>
#include <iostream>
using namespace std;
//Declaration of global variables
int delayTime;
//Gets executed once to setup parameters
static int setup() {
delayTime = 750;
}
//Gets executed until ESC is pressed
static int program() {
set(0, 1); //FIRST ERROR
set(5, 0);
delay(delayTime);
set(0, 0);
set(5, 1);
delay(delayTime);
}
//Main function getting called at program start
int main() {
bool running = true;
setup();
puts("Press 'STRG+C' to exit the program. Then run './off'");
if (wiringPiSetup() == -1)
return 1;
pinMode(0, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
set(4, 1); //SECOND ERROR
while (running) {
program(); //Run the code above
}
digitalWriteByte(0);
return 0;
}
//Shortcuts for basic functions
static int set(int pin, int state) {
digitalWrite(pin, state);
return 0;
}
static int get(int pin) {
return digitalRead(pin);
}
You are calling set() before it has been declared. Either move the function up in the file, so that it is above the first place it is called, or add a forward declaration like this:
static int set(int pin, int state);
C/C++ compilers are dumb — they proceed top-down. At the time that you call set() from main(), the compiler still doesn't know what set() is yet, because it hasn't seen the definition.
One solution is to write an explicit declaration of set() before main() is defined. An easier approach would be to move main() to the end, as is conventional — precisely because of this issue.
C++ compilation is dependent on order. If you call something that was not yet declared, you get an error. Either move your functions body to a place before it's called, or place a forward declaration there.

Visual Studio Compiler is highlighting Static variables differently?

I'm programming in C++ and have a method which uses a static variable. The method isn't working as I think it should; upon investigation, I found that my static variable is being highlighted in red in two places and blue in other places. Below is the code:
int GameModeState::changeJob(int number)
{
static int job = 1; //red
if (number == 1)
{
job = (job+1); //First one is red, second one is blue
return job; //blue
} else {
return job; //blue
}
}
I'm calling this method with other methods, one shown for example:
int GameModeState::getJob()
{
int currentJob = (changeJob(2));
return currentJob;
}
I want a method like getJob() to simply return the current value of job, while another method, when calling changeJob(number) is changeJob(1), to increment job's value by one. (Hence the if/else statement in changeJob(number)).
Since the job variables are highlighted differently, I'm thinking the compiler is saying that it views the two separately somehow? I'm getting stuck with job being some even value.
EDIT I also have Awesomium... I believe that is the only addition to the compiler, but I'm not completely sure.
MOAR EDIT In another class, I have a method which should determine the current job's number and do something based on if the number is even or odd (since right now there are only two jobs)
void ZoneMovementState::_changeZone(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
//Awesomium::JSValue::Object object = input.getObject();
//String zoneFilename = Convert::toString(object[L"zoneFilename"].toString());
// If the number from getJob is even, the player is currently a geologist
if (GameModeState::getJob()%2 == 0)
{
ZoneParser::getSingleton().load("../media/zones/geology_zone.xml", false);
} else {
ZoneParser::getSingleton().load("../media/zones/farm_zone.xml", false);
}
transitionHandler->go();
}
Ignore the two commented out lines; they deal with JS, which I'm not working on for now.
In the program, I can access the farm_zone until I increment job's value using the below method in GameModeState:
void GameModeState::_openNotebook(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
mNotebookTransition->go();
static int currentJob = changeJob(1);
}
.... So I figured out my problem. While going through the code to show you guys, I realized that the static for currentJob was probably unneeded... once I removed it, my code works as it should now.
Thanks for the help guys!
Part of the problem here is you're using a static local for what very likely should just be a member variable. A static local maintains it's value across all calls to a function in all threads in a process. It's much more likely that you want it to persist for all calls to changeJob in a particular GameModeState instance (else why make it a member functon to begin with?).
To do this you'll need to define a member variable on GameModeState initialize it in the constructor and then access it in the method. For example
class GameModeState {
int job;
GameModeState() : job(1) {}
int changeJob(int number);
};
int GameModeState::changeJob(int number) {
if (number == 1) {
job = (job+1);
return job;
} else {
return job;
}
}
Note: I'm not entirely sure why you're seeing the color's your are seeing. Visual Studio by default won't color member variables a particular color in C++ so it's very likely another add-in you are using.
Nah, highlighting doesn't mean anything. That is, the editor doesn't call the compiler before deciding how/what/when to highlight. So that is not your problem. Sorry 'bout that :-)
You can prove this to yourself by going to Tools->Options->TextEditor and noticing that you can change the highlighting by choosing a different text-editing model.