The attributes of my child class are lazily initialized - c++

I have created a parent class in C++ and one child class which I have two attributes: _trigger and _echo. In order to use my child class I declare it and I assign its address to a pointer of the parent class. Hence, I use the methods of my parent class.
My problem: When I use the method cyclePulse without parameters (int trigger, int echo) and the attributes from my class (_trigger and _echo), the method does not work properly. I guess it is because the attributes _trigger and _echo are lazily initialized, or because I am not using new keyword when I am creating my object.
class ISensor {
...
public:
ISensor();
virtual ~ISensor();
...
virtual int connect() = 0;
virtual char * readRequest() = 0;
virtual int disconnect() = 0;
};
class HCSR04: public ISensor {
private:
int _trigger;
int _echo;
public:
HCSR04();
HCSR04(int trigger, int echo);
...
int connect();
char * readRequest();
uint64_t cyclePulse(int trigger, int echo);
float distanceCentimeters();
};
Here is the implementation of HCSR04.cpp. Edited: I forgot the constructors.
HCSR04::HCSR04() {
_echo = RPI_V2_GPIO_P1_13;
_trigger = RPI_V2_GPIO_P1_15;
}
HCSR04::HCSR04(int trigger, int echo) {
_echo = echo;
_trigger = trigger;
}
char * HCSR04::readRequest() {
float preCent = distanceCentimeters();
char* buf = new char[20];
sprintf(buf, "%.10f", preCent);
return buf;
}
float HCSR04::distanceCentimeters() {
return (float) cyclePulse(_trigger, _echo) / 55.5;
}
uint64_t HCSR04::cyclePulse(int trigger, int echo) {
uint64_t width, begin, start, end;
int max = 80, check;
begin = bcm2835_st_read();
// Emit pulse for 10 microseconds
bcm2835_gpio_write(_trigger, HIGH); // Set trigger state HIGH
bcm2835_delayMicroseconds(10); // Wait 10 microseconds
bcm2835_gpio_write(_trigger, LOW); // Set trigger state LOW
while (bcm2835_gpio_lev(_echo) == LOW && check < max) {
start = bcm2835_st_read();
check = (int) begin - start;
}
while (bcm2835_gpio_lev(_echo) == HIGH) {
bcm2835_delayMicroseconds(1);
}
end = bcm2835_st_read();
width = end - start;
return width;
}
I am using the class like this:
HCSR04 deviceUltrasonic;
ISensor * sensorUltrasonic = &deviceUltrasonic;
char* readRequestArray = sensorUltrasonic->readRequest();

Giving my previous comment as a possible answer here, because I assume that the uninitialized variables are causing your fault here:
uint64_t HCSR04::cyclePulse(int trigger, int echo) {
uint64_t width, begin, start, end;
int max = 80, check = 0; // <<< init check to 0.
// Btw: size_t or any other unsigned type matches
// better the purpose of what you want to achieve.
begin = bcm2835_st_read();
// begin is not used afterwards. Did you mean to initialize "start" here?
start = begin;
// Emit pulse for 10 microseconds
bcm2835_gpio_write(_trigger, HIGH); // Set trigger state HIGH
bcm2835_delayMicroseconds(10); // Wait 10 microseconds
bcm2835_gpio_write(_trigger, LOW); // Set trigger state LOW
while (bcm2835_gpio_lev(_echo) == LOW && check < max) {
start = bcm2835_st_read();
check = (int) begin - start;
}
while (bcm2835_gpio_lev(_echo) == HIGH) {
bcm2835_delayMicroseconds(1);
}
end = bcm2835_st_read();
width = end - start;
return width;
}

Related

C++ (Arduino), Can't update object when accessing it as attribute of another object

I have recently bought an Arduino which uses C++ to code on. I am familiar with Java and as C++ allows OO programming I didn't think it would have been that difficult. But...
CODE:
// LEDCLOCK CLASS /////////////////////////////////////////////////////////////////////////
class LedClock{
private:
int hours;
int minutes;
int seconds;
static const long secondInterval = 1000;
unsigned long previousMilliseconds;
unsigned long currentMilliseconds;
public:
LedClock(){
hours = 0;
minutes = 0;
seconds = 0;
previousMilliseconds = 0;
currentMilliseconds = 0;
};
int getHours(){
return hours;
};
int getMinutes(){
return minutes;
};
int getSeconds(){
return seconds;
};
long getSecondInterval(){
return secondInterval;
};
unsigned long getPreviousMilliseconds(){
return previousMilliseconds;
};
void setHours(int h){
if(h < 24 && h >= 0){
hours = h;
}else{
hours = 0;
}
};
void setMinutes(int m){
if(m < 60 && m > 0){
minutes = m;
}else{
minutes = 0;
}
};
void setSeconds(int s){
if(s < 60 && s > 0){
seconds = s;
}else{
seconds = 0;
}
};
void setPreviousMilliseconds(unsigned long ms){
previousMilliseconds = ms;
};
void increaseOneHour(){
// as there is no day counter to increment atm this if-else statement is a bit useless.
// setHour(getHours() + 1) would have sufficed here with the current setter
if(getHours()==23){
setHours(0);
}else{
setHours(getHours() + 1);
}
};
void increaseOneMinute(){
if(getMinutes() == 59){
increaseOneHour();
setMinutes(0);
}else{
setMinutes(getMinutes() + 1);
}
};
void increaseOneSecond(){
if(getSeconds() == 59){
increaseOneMinute();
setSeconds(0);
}else{
setSeconds(getSeconds() + 1);
}
};
void tick(){
currentMilliseconds = millis();
if(currentMilliseconds - getPreviousMilliseconds() >= getSecondInterval()){
setPreviousMilliseconds(currentMilliseconds);
increaseOneSecond();
}
};
};
// LEDCLOCKCONTROLLER CLASS ////////////////////////////////////////////////////////////////
class LedClockController{
private:
LedClock ledClock;
int mode = 2;
public:
LedClockController(LedClock lc){
ledClock = lc;
};
LedClock getLedClock(){
return ledClock;
};
int getMode(){
return mode;
};
void setMode(int newMode){
mode = newMode;
};
};
// ARDUINO CODE /////////////////////////////////////////////////////////////////////////
LedClock lc = LedClock();
LedClockController lcc(lc);
void setup() {
Serial.begin(9600); //Begin serializer to print out value
}
void loop() {
//doesn't give me updated values
if(lcc.getLedClock().getPreviousMilliseconds()<63000){
Serial.println(lcc.getLedClock().getSeconds());
lcc.getLedClock().tick();
}
//does give me updated values
//commented out for now
/*
if(lc.getPreviousMilliseconds()<63000){
Serial.println(lc.getSeconds());
lc.tick();
}
*/
}
Q1:
I have difficulties to update attributes of my LedClock attribute in my Controller class.
When I target the LedClock by itself, everything runs fine but when I would update it via the Controller, then it wouldn't. In short, when getting the seconds in the first case, I could see the increment in values in the output. When I did the same thing but via the controller, the seconds stayed 0.
So I am missing something vital here. Can someone help/explain what I am missing?
Q2: Ideally I would want to create the LedClock object inside the constructor but didn't seem to find how to.
I tried things that could make sense but with the issues I have been having, I was holding off on this:
LedClockController lcc(LedClock lc());
LedClockController lcc(LedClock);
//would make sense to me, I noticed C++ doesn't use the 'new' keyword so have no idea how to do that then
LedClockController lcc(LedClock());
All of those ran into compilation issues so probably another important C++ thing that I haven't taken into account.
P.S. I have been noticing that there are some different views on getter and setters (accessing the attributes directly vs actual functions). I have been using the method I am used to (and were mentioned on W3schools) because I will rely on setting logic in 1 place.

Extend photo-diode detector to support multiple sensors

I am quite new to C++, so I was hoping someone can help me answer my question. I am building an embedded system using Arduino.
I have a number of photo-diodes that generate an event when an physical object passes the sensor. The object passes the sensor too quickly, so the signal is short-lived and on non deterministic length. So I wish to implement a timer that holds the state to a period following detection.
The following code is my attempt to implement this for a single photo-diode sensor, (Note: I have not tried to compile it yet, there might be some mistakes). However how can I extend this to support multiple sensors.
Here is code:
struct DiodeResult {
bool diodePassed;
unsigned long timeOfSet;
}
void loop() {
static DiodeResult diodeResult;
bool diodePassed = readDiode();
if (diodePassed) {
diodeResult.diodePassed = true;
diodeResult.timeOfSet = millis();
} else {
if ((millis() - diodeResult.timeOfSet) > (5*1000) {
diodeResult.diodePassed = false;
}
}
}
Your existing solution can be extended to handle multiple photo-diodes simply by using an array of DiodeResult instances:
void loop()
{
static DiodeResult diodeResult[DIODE_COUNT];
for( int i = 0; i < DIODE_COUNT; i++ )
{
bool diodePassed = readDiode( i ) ;
if( diodePassed )
{
diodeResult[i].diodePassed = true;
diodeResult[i].timeOfSet = millis();
}
else
{
if( (millis() - diodeResult[i].timeOfSet) > (5 * 1000)
{
diodeResult[i].diodePassed = false;
}
}
}
}
Or perhaps more "Arduino-like":
void loop()
{
static DiodeResult diodeResult[DIODE_COUNT];
static int i= 0 ;
bool diodePassed = readDiode( i ) ;
if( diodePassed )
{
diodeResult[i].diodePassed = true;
diodeResult[i].timeOfSet = millis();
}
else
{
if( (millis() - diodeResult[i].timeOfSet) > (5 * 1000)
{
diodeResult[i].diodePassed = false;
}
}
// Next diode on next loop iteration
i = (i + 1) % DIODE_COUNT ;
}
However it relies on the photo-diode state remaining active for at least as long as it takes to iterate all ten sensors. This may be the case, but it highly dependent on your application and possibly the implementation of readDiode(). It may be necessary if polling is not fast enough to use interrupts.
Moreover the solution could arguably be improved by a little OOP:
class cMonoStable
{
public :
cMonoStable( unsigned long period_ms ) : m_time_ms(time_ms)
{
}
void trigger()
{
m_start_ms = millis() ;
}
bool getState()
{
return m_start_ms - millis() < m_time_ms ;
}
private :
unsigned long m_time_ms;
unsigned long m_start_ms
};
class cPhotoDiodeTriggeredMonostable : public cMonoStable
{
public :
cPhotoDiodeTriggeredMonostable( unsigned long period_ms, int diode = 0 ) : cMonoStable( period_ms ) : m_diode(diode)
{
}
void update()
{
if( readDiode( m_diode ) )
{
trigger() ;
}
}
private:
int m_diode ;
} ;
static const int DIODE_COUNT = 10 ;
static cPhotoDiodeTriggeredMonostable* photo_diode_state[DIODE_COUNT];
void setup()
{
for( int i = 0; i < DIODE_COUNT; i++ )
{
photo_diode_state[i] = new cPhotoDiodeTriggeredMonostable( 5000, i ) ;
}
}
void loop()
{
static int i = 0 ;
photo_diode_state[i]->update() ;
if( photo_diode_state[i].getState() )
{
// do whatever - state remains true for 5 seconds after diode was last active.
}
}
It looks a little long winded, but not how simple the individual elements are, and the cMonoStable class can be applied to other sensor types with similar characteristics, just be implementing a super-class with a different update() implementation.

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) {

Why is a struct member uninitialized after dereferencing the struct

I'm writing an HBridge class to make handling HBridges one arduino much easier. I'm not sure why I call .print() on my HBridge instance, it prints:
---------
BRIDGE ONE
Bridge Use:->pin: 1392293344
Bridge Idle->pin: 1392293408
Freq:0
Dir:0
---------
BRIDGE TWO
Bridge Use:->pin: 8
Bridge Idle->pin: 214125355
Freq:0
Dir:0
Notice how the Bridge Use and Bridge Idle is uninitialized. Am I making a mistake somewhere with my pointers?
Here is my code.
HBridge.h
//-----------------------|
#define true 1 //|
#define false 0 //|
//-----------------------|
#define PIN_OFF 0 //|
#define PIN_ON 1 //|
//-----------------------|
#define PIN_FORWARD 0 //|
#define PIN_BACKWARD 1//|
//-----------------------|
typedef struct{
int pin;
} Pin;
typedef struct {
Pin *inuse;
Pin *idle;
int freq;
int direction;
}Bridge;
typedef enum{ A, B} hbridge_pins;
class HBridge {
private:
Bridge bridge_a, bridge_b;
Bridge *pins[2];
public:
HBridge(int, int, int, int);
void setPinFrequency(hbridge_pins, int);
void setPinDir(hbridge_pins, int);
void turnPinOFF(hbridge_pins);
void update(void);
void print();
};
HBridge.cpp
#import "./HBridge.h"
#import <stdio.h>
Pin pinWith(int num) {
// pinMode(num, OUTPUT);
Pin p;
p.pin = num;
return p;
}
void swap_pins(Pin *a, Pin *b) {
Pin temp = *a;
*a = *b;
*b = temp;
}
void print_pin(const char * name, Pin *p){
printf("%s->pin: %d\n",name,p->pin);
}
void print_bridge(Bridge *b){
print_pin("Bridge Use:", b->inuse);
print_pin("Bridge Idle", b->idle);
printf("Freq:%d\nDir:%d\n",b->freq,b->direction);
}
void HBridge::turnPinOFF(hbridge_pins pin) {
pins[pin]->freq = PIN_OFF;
}
HBridge::HBridge(int pinAA, int pinAB, int pinBA, int pinBB) {
Pin a_use = pinWith(pinAA);
Pin a_idle = pinWith(pinAB);
Pin b_use = pinWith(pinBA);
Pin b_idle = pinWith(pinBB);
bridge_a.inuse = &a_use;
bridge_a.idle = &a_idle;
bridge_b.inuse = &b_use;
bridge_b.idle = &b_idle;
/*---(DEFAULT DIRECTIONS)---*/
bridge_a.direction = PIN_FORWARD;
bridge_b.direction = PIN_FORWARD;
bridge_a.freq = PIN_OFF;
bridge_b.freq = PIN_OFF;
/*---(ARRAY OF POINTERS TO THE TWO PINS FOR EASY ACCESS BY INDEX)---*/
pins[0] =&bridge_a;
pins[1] =&bridge_b;
}
void HBridge::setPinFrequency(hbridge_pins pin, int freq) {
pins[pin]->freq = freq;
}
void HBridge::setPinDir(hbridge_pins pin, int dir) {
if ((pins[pin]->direction == PIN_FORWARD && dir == PIN_FORWARD) || (pins[pin]->direction == PIN_BACKWARD && dir == PIN_BACKWARD)) {
} else if (pins[pin]->direction == PIN_FORWARD && dir == PIN_BACKWARD) {
/*----(SWAP POINTERS)----*/
swap_pins(pins[pin]->inuse, pins[pin]->idle);
pins[pin]->direction = PIN_BACKWARD;
} else if (pins[pin]->direction == PIN_BACKWARD && dir == PIN_FORWARD) {
/*----(SWAP POINTERS)----*/
swap_pins(pins[pin]->inuse, pins[pin]->idle);
pins[pin]->direction = PIN_BACKWARD;
}
}
void HBridge::update(void)/*pointer to an int to save memory*/ {
/*THE FIRST BRIDGE*/
// analogWrite(pins[0]->inuse->pin, pins[0]->freq);
// analogWrite(pins[0]->indle->pin, pins[0]->PIN_OFF);
// THE SECOND BRIDGE
// analogWrite(pins[1]->inuse->pin, pins[1]->freq);
// analogWrite(pins[1]->indle->pin, pins[1]->PIN_OFF);
}
void HBridge::print(void){
printf("---------\nBRIDGE ONE\n");
print_bridge(pins[0]);
printf("---------\nBRIDGE TWO\n");
print_bridge(pins[1]);
}
int main(int argc, const char*argv[]){
HBridge b(31,42,33,4);
b.setPinFrequency(A,200);
b.print();
}
Pin a_use is local to the constructor and you are making a pointer from it, although it will be deallocated when the contsructor returns.
Declare inuse and idle as Pin inuse; and Pin idle; and don't make a pointer, just assign to them what pinWith() returns, the value will be copied and the problem will be gone.
If you need them to be pointers, then first request heap space like this
bridge_a.inuse = new Pin;
and then do this
memcpy(bridge_a.inuse, &a_use, sizeof(Pin));
if the Pin doesn't contain any class but just POD fields, it will work, otherwise a more elaborated copy will be needed.
Echoing #iharob. You have the same problem in the pinWith() function where you return a Pin off the stack for the pinWith() function, a position which becomes "garbage" once you return from the function. You'll need to allocate a Pin from the heap in pinWith() to fix this.
Pin pinWith(int num) {
// pinMode(num, OUTPUT);
Pin p = new Pin;
p.pin = num;
return p;
}

Function/method definition error in Arduion/C++. Or syntax error?

I'm translating a program I wrote in Ruby to the Arduino/C++. On my first attempt to define a function/method I keep getting the following error: "BreadboardTestFunctions:41: error: a function-definition is not allowed here before '{' token
BreadboardTestFunctions:91: error: expected `}' at end of input"
Hard to understand because the function-definition must be followed by a pair of brackets. This could reflect a syntax error as it has persisted as I've corrected a score of errors in the function as I've tried to solve this problem. But it looks OK to me now.
I'm generating an output after matrix multiplication in the section beginning "// routine to multiply: behavior=brain * stimulus'". Although the problematic method, "mody" (at line 40) is only called once now, once I get it to work all the outputs will call it.
The code:
/* BREADBOARD
Implement program on Arduino + breadboard
*/
// constants
int foodPin = 2; // to provide food
int painPin = 3; // to punish
int ucsPin = 4; // the UCS
int csPin = 5; // the CS
int lightPin = 6; // turn the "light" stim on/off
int thresh = 700;
// variables
int buttonState = 0; // variable for reading the pushbutton status
boolean lighton = false;
unsigned short int energy = 10000;
int stimulus[11] = {0,0,0,0,0,0,0,0,0,0,0};
int brain[7][11] = { {0,0,0,0,99,0,0,0,0,1,0},
{0,0,0,0,0,99,0,0,0,1,0},
{0,0,0,0,0,0,99,0,0,1,0},
{90,0,0,0,0,0,0,1,-1,1,-99},
{0,90,0,0,0,0,0,1,-1,1,1},
{0,0,90,0,0,0,0,1,-1,1,1},
{0,0,0,90,0,0,0,1,-1,1,1} };
int behavior[7] = {0,0,0,0,0,0,0};
void setup() {
// initialize the pushbutton pins as an input:
pinMode(foodPin, INPUT);
pinMode(painPin, INPUT);
pinMode(ucsPin, INPUT);
pinMode(csPin, INPUT);
pinMode(lightPin, INPUT);
Serial.begin(9600);
int ix=0;
// define behavioral methods
void mody (int ix, int brain[], int stimulus[])
{ int psp=20;
int j;
for(j=7;j<11;j++)
{if (brain[ix][j] > 0) brain[ix][j]+= stimulus[j] * (99-brain[ix][j])/psp;
if (brain[ix][j] < 0) brain[ix][j]+= -1*(stimulus[j] * abs(99-brain[ix][j])/psp);}
return;}
} // end void setup
void loop(){
// decay stimulus vector. do this and check inputs for ALL stimulii later
int k;
for(k=0;k<11;k++)
{if (stimulus[k] > 1) stimulus[k]-=2; else stimulus[k]=0;}
//check inputs
buttonState = digitalRead(foodPin);
if (buttonState == HIGH) stimulus[4] = 9;
buttonState = digitalRead(painPin);
if (buttonState == HIGH) stimulus[5] = 9;
buttonState = digitalRead(ucsPin);
if (buttonState == HIGH) stimulus[6] = 9;
buttonState = digitalRead(lightPin);
if (buttonState == HIGH) {stimulus[7] = 9; stimulus[8] = 9;lighton = true;}
else {stimulus[7] = 0; stimulus[8] = 0;lighton = false;}
buttonState = digitalRead(ucsPin);
if (buttonState == HIGH) stimulus[6] = 9;
// routine to multiply: behavior=brain * stimulus'
int i, j;
for(i=0;i<7;i++)
{ behavior[i]=0;
for (j=0;j<11;j++)
{behavior[i]= behavior[i]+stimulus[j]*brain[i][j]; }
} // end for i
if (behavior[0] > thresh) {Serial.println("Positive Fixer");}
if (behavior[1] > thresh) {Serial.println("Negative Fixer");}
if (behavior[2] > thresh) {Serial.println("UCR"); mody (2, brain[], stimulus[]);}
if (behavior[3] > thresh) {Serial.println("Operant one");}
if (behavior[4] > thresh) {Serial.println("Operant two");}
if (behavior[5] > thresh) {Serial.println("Operant three");}
if (behavior[6] > thresh) {Serial.println("Operant four");}
// generate random operant
if (random(energy) < 10) stimulus[random(4)]= 9 + random(3);
energy --;
Serial.println(energy);
} // end void loop
You may not define one function inside another function. It is what you are trying to do in the following code snippet
void setup() {
// initialize the pushbutton pins as an input:
pinMode(foodPin, INPUT);
pinMode(painPin, INPUT);
pinMode(ucsPin, INPUT);
pinMode(csPin, INPUT);
pinMode(lightPin, INPUT);
Serial.begin(9600);
int ix=0;
// define behavioral methods
void mody (int ix, int brain[], int stimulus[])
You are trying to define function mody inside function setup.