Arduino servo object does not work within my own library - c++

I have written a libary for somebody else to slowly sweep servo's from one position to another. It did not work like I intented and I had to remove the servo objects from the library. Instead I let the new version calculate the servo positions and return those values instead. Yet I really like to know why it is not working.
The header file with the private Servo objects
#include <Arduino.h>
#include <Servo.h>
class ServoSweep {
public:
ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed ) ; // constructor 1
ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed, byte _relayPin ) ; // constructor 2
void sweep( );
void setState( uint8_t _state );
private:
Servo servo ;
unsigned long timeToRun ;
byte pos ;
byte state ;
byte prevPos;
byte servoPin ;
byte servoSpeed ;
byte servoMin ;
byte servoMax ;
byte middlePosition ;
byte relayPresent ;
byte relayPin ;
} ;
And the source file:
#include "ServoSweep.h"
ServoSweep::ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed ) { // constructor 1
servoPin = _servoPin ;
servoSpeed = _speed ;
servoMin = _min ;
servoMax = _max ;
middlePosition = ( (long)servoMax - (long)servoMin ) / (long)2 + (long)servoMin ; // start with middle position
pos = middlePosition ;
servo.write( pos ) ;
servo.attach( servoPin ) ;
}
ServoSweep::ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed, byte _relayPin ) { // constructor 2
servoPin = _servoPin ;
servoSpeed = _speed ;
servoMin = _min ;
servoMax = _max ;
middlePosition = ( (long)servoMax - (long)servoMin ) / (long)2 + (long)servoMin ;
pos = middlePosition ;
servo.write( pos ) ;
servo.attach( servoPin ) ;
relayPresent = 1;
relayPin = _relayPin ;
pinMode( relayPin, OUTPUT ) ;
}
void ServoSweep::sweep () {
if( millis() > timeToRun ) {
timeToRun = millis() + servoSpeed ;
if( state ) {
if( pos < servoMax ) pos ++ ;
}
else {
if( pos > servoMin ) pos -- ;
}
if( prevPos != pos ) {
prevPos = pos ;
if( relayPresent == 1 ) {
if( pos < middlePosition ) digitalWrite( relayPin, LOW ) ;
else digitalWrite( relayPin, HIGH ) ;
}
servo.write( pos ) ;
}
}
}
void ServoSweep::setState( uint8_t _state ) {
state = _state ;
}
The servo signal was complete jitter caused by the arduino. The example sketch I used:
#include "ServoSweep.h"
const int inputButton = 12 ;
const int servoPin1 = 2 ;
const int servoPin2 = 3 ;
unsigned long prev ;
byte state ;
// pin min max speed (bigger speed = slower movement ;
ServoSweep servo1(servoPin1, 10, 30, 50) ;
ServoSweep servo2(servoPin2, 10, 30, 50) ;
void setup() {
pinMode( inputButton, INPUT_PULLUP ) ;
}
void loop() {
servo1.sweep();
servo2.sweep();
if( digitalRead( inputButton ) ) servo1.setState( 1 ) ;
else servo1.setState( 0 ) ;
if( digitalRead( inputButton ) ) servo2.setState( 0 ) ;
else servo2.setState( 1 ) ;
}
Even I comment out al code inside the loop, the jitter is there. The jitter starts as soon as I construct the ServoSweep objects.
What did I wrong with the servo objects? I assume this has to be possible.

The problem is most likely in your constructor. These lines:
servo.write( pos ) ;
servo.attach( servoPin ) ;
in the constructor are trying to work with hardware that may not be ready yet. You are calling the constructor at global scope, so these things may be happening before init() runs and sets up the hardware. So when init() does run, it is probably overwriting values that the servo library had written to timer 1.
This is a common issue and a common newbie trap. Constructors should initialize variables and set up values and things, but they are not for handling hardware. For that you need a begin() or init() method that you can call from setup. Think about how the servo library has the attach function that you have to call from setup. If it were possible to do that in the constructor, they would have had the constructor take the pin number and do it. Think about the begin method that you have to call for Serial to work. That's the same story, there's hardware to setup and you need to be able to control when that happens.
So make one more method:
void ServoSweep::begin() {
servo.write( pos ) ;
servo.attach( servoPin ) ;
}
And call that from setup for each object and remove those lines from the constructor.

Related

C++ inheritence and array

I have a java program with which I create a program using logic function blocks. AND gates, OR gates that sorta things. This program can generate functional source code for an arduino board. This essentially allows people to program an Arduino with only logic gates.
The core essentials work but I am only halfway there and I run into a slight problem.
I have this struct and array
typedef struct blox
{
uint8_t IN1 : 1 ; // generic for most blocks
uint8_t IN2 : 1 ; // generic for most blocks
uint8_t IN3 : 1 ; // generic for most blocks
uint8_t Q : 1 ; // generic for most blocks
uint8_t pin : 5 ; // only inputs and output types need this
uint8_t type : 4 ; // 16 combinations
uint32_t oldTime ; // bad idea to use this amount of memory per block if only delays need it?
const uint32_t interval ; // perhaps couple a function pointers or obj pointer to it?
} FunctionBlock ;
FunctionBlock block [ nBlocks ] ;
In the main loop() I run all logic and I update the links. The links are hardcoded.
void loop()
{
/***************** UPDATE FUNCTION BLOCKS *****************/
for( int i = 0 ; i < nBlocks ; i ++ )
{
switch( block[i].type )
{
case AND:
block[i].Q = block[i].IN1 & block[i].IN2 & block[i].IN3 ; // unused inputs INx are initialized to '1'
break ;
case OR:
block[i].Q = block[i].IN1 | block[i].IN2 | block[i].IN3 ;
break ;
case M:
if( block[i].IN3 ) block[i].Q = 0 ; // R
else if( block[i].IN1 ) block[i].Q = 1 ; // S
break ;
case NOT:
block[i].Q = !block[i].IN2 ;
break ;
case INPUT_PIN:
block[i].Q = digitalRead( block[i].pin ) ;
break ;
case OUTPUT_PIN:
digitalWrite( block[i].pin, block[i].IN2 ) ;
break ;
case DEL: for( int i = 0 ; i < n_blocks ; i ++ )
{
if( block[i].Q != block[i].IN ) // if new state changes
{
if( millis() - block[i].oldTime >= block[i].interval ) // keep monitor if interval has expired
{
block[i].Q = block[i].IN ; // if so, adopt the new state
}
}
else
{
block[i].oldTime = millis() ; // if new state does not change, keep setting oldTime
}
}
break ;
}
}
/***************** UPDATE LINKS *****************/
block[3].IN2 = block[1].Q ; // hardcoded list of all links.
block[3].IN1 = block[0].Q ;
block[3].IN3 = block[2].Q ;
block[4].IN2 = block[3].Q ;
} ;
The problem is that the structure has variables for everything. Now AND and OR gates have a 'pin' variable and every block uses 8 bytes for timing, despite only the delay gate has need for it.
I also want to add analog (all that can be more than '0' or '1') components, like an analog input, servo motor, a map() block (to map one range into an other range), comparator contants etc.
Using the struct like this will consume way too much memory.
My best guess would be to use classes and inheritance. But I haven't used inheritance yet in c++ and I do not know how I can stuff objectes and derived objects in a single array.
class FunctionBlock // AND, OR, MEMORY or NOT gates
{
public:
uint8_t IN1 : 1 ;
uint8_t IN2 : 1 ;
uint8_t IN3 : 1 ;
uint8_t Q : 1 ;
uint8_t type ; // if I create derived classes for OR, AND, MEMORY and not gates, I may discard this variable
} ;
class IO : public FunctionBlock // INPUT, OUTPUT
{
uint8_t pin ;
} ;
class DELAY : public FunctionBlock
{
uint32_t prevTime ;
const int delayTime ;
} ;
class MAP : public FunctionBlock
{
int32_t var ; // result = map( var, in1, in2, out1, out2 ) ;
int32_t result
int32_t in1 ;
int32_t in2 ;
int32_t out2 ;
int32_t out2 ;
} ;
// class analogIn, class constant, class comperator, class decadeCounter etc etc
Were this Java I would simply do:
ArrayList <FunctionBlock> blocks = new ArrayList() ;
...
blocks.add( new AND( arguments ) ;
How do I get these derived classes to work in c++ ?
I think it might be better to define the separate structures without inheritance, and then use a union in the FunctionBlock structure to keep the data.
Perhaps something like this:
struct IO
{
uint8_t pin;
};
struct DELAY
{
uint32_t prevTime;
const int delayTime;
};
// ... the other structures...
struct FunctionBlock
{
// The current members of the structure...
union
{
IO io;
DELAY delay;
// ... and the other structures...
};
};
Then you can use e.g. block[i].io.pin to get the IO member pin.
Now you can just use the FunctionBlock structure as any other structure, and create a plain normal array.
I chose to go for inheritence as a union would not really solve the memory problem. And performance is in this case not really important. As in it does not matter if this program run 'efficient' or not.
I declare objects using the subclasses followed by a pointer array.
#include "functionBlocks.h"
static Input b1 = Input(1) ;
static Input b2 = Input(2) ;
static Input b3 = Input(3) ;
//static Or b4 = Or() ; // if I swap this Or gate for a Delay gate
static Delay b4 = Delay(2000) ; // RAM consumes 4 more bytes as anticipated.
static Delay b5 = Delay( 3000 ) ;
static Output b6 = Output(13) ;
FunctionBlock *block[] =
{
&b1,
&b2,
&b3,
&b4,
&b5,
&b6,
} ;
const int nBlocks = 6 ;
void setup()
{
}
void loop()
{
block[3] -> IN1 = block[0] -> Q ;
block[3] -> IN2 = block[1] -> Q ;
block[3] -> IN3 = block[2] -> Q ;
block[4] -> IN2 = block[3] -> Q ;
block[5] -> IN2 = block[4] -> Q ;
/***************** UPDATE FUNCTION BLOCKS *****************/
for( int i = 0 ; i < nBlocks ; i ++ ) block[i] -> run() ;
} ;
I tested the memory consumption by swapping out an OR gate for a DELAY and that increases memory usage by 4 bytes. This is correct because the DELAY uses one whole uint32_t variable on top the base class.
So using subclasses like this does resolve the memory problem.
If I now add a single OR gate, RAM only consumes five more bytes. One byte is used for the variables, IN1, IN2, IN3 and Q but I cannot place the other 4 bytes. I am guessing it is a function pointer to the appropiate run()method.
I also moved all the classes to a seperate header file. It looks as follows:
class FunctionBlock
{
public:
uint8_t IN1 : 1 ;
uint8_t IN2 : 1 ;
uint8_t IN3 : 1 ;
uint8_t Q : 1 ;
virtual void run() ;
} ;
class And : public FunctionBlock
{
public:
And()
{
IN1 = IN2 = IN3 = 1 ;
}
void run()
{
Q = IN1 & IN2 & IN3 ;
}
} ;
class Or : public FunctionBlock
{
public:
Or()
{
IN1 = IN2 = IN3 = 0 ;
}
void run()
{
Q = IN1 | IN2 | IN3 ;
}
} ;
class Delay : public FunctionBlock
{
public:
Delay(int x) : delayTime( x ) // initialize the constant
{
}
void run()
{
if( Q != IN2 ) // if new state changes
{
if( millis() - prevTime >= delayTime ) // keep monitor if interval has expired
{
Q = IN2 ; // if so, adopt the new state
}
}
else
{
prevTime = millis() ; // if new state does not change, keep setting oldTime
}
}
private:
const uint32_t delayTime ;
uint32_t prevTime ;
} ;

button that turns off all features

I am new to coding and embedded systems and I wanted to make a button that turns off and on a LED and at the same time turn off all other futures in the system.
So far I had the button turn off and on but I cant seem to get it to also update the Potentiometer. For some reason the code would check if the button is pressed and if so then the LED would turn on and then check if the LED is on and if so then turn on the other LEDs but when I change the value of the Potentiometer( which should switch to other LEDs) it would not update and stay on the same LED. So my question is how can I put another if statement that would keep updating in the while loop?
the code that I wanted to keep updating while the first LED is on is the "else if code"
Hope that made sense.
:)
note:
I don't know if my approach is right as I am looking at the LED and not the button it self, as my code checks if the LED is on rather then if the button is pressed.
(btw its not a switch which would have made my life a lot easier :( )
#include "mbed.h"
DigitalIn userButton (PC_10);
DigitalOut led (PC_0);
bool buttonDown = false;
BusOut leds_bus (PC_1, PB_0, PA_4);
AnalogIn pot1 (PA_5);
void init_leds ();
int cntl_val = 0;
int main ()
{
cntl_val = pot1.read_u16 () / 32768;
while (true)
{
// run forever
if (userButton.read () == true)
{
// button is pressed
if (!buttonDown)
{
// a new button press
led = !led; // toogle LED
buttonDown = true; // record that the button is now down so we don't count one press lots of times
ThisThread::sleep_for (100);
}
else if (led.read () == true)
{
if (cntl_val < 1 / 3)
{
leds_bus.write (4);
}
if (cntl_val > (1 / 3) && cntl_val < (2 / 3))
{
leds_bus.write (2);
}
if (cntl_val > (2 / 3))
{
leds_bus.write (1);
}
}
}
else
{
// button isn't pressed
buttonDown = false;
}
}
}
You need to fix your math. int cntl_val is an integer so comparing it with the fractions 1/3 and 2/3 is not going to do what you expect. And cntl_val = pot1.read_u16()/32768; can set cntl_val to only 0 or 1. If the max value returned by pot.read_u16() is less than 32768 then cntl_val will only be 0.
You could maybe change cntl_val to a float but that's probably not the best option.
Instead, try setting cntl_val = pot1.read_u16(); (don't divide by 32768). And then compare cntl_val with (32768/3) and (32768*2/3). That's still ugly but better.
It is not clear from your description, but I am assuming that you have:
An on/off indicator LED
A three-LED level indicator
A momentary action button for on/off control
A potentiometer to control the input level.
And that when the system is in the "on" state you wish to indicate the potentiometer level on the level indicator? That being the case, I suggest:
Deal with button input/debounce separately from LED state determination.
Simplify the level setting; you have a level 0, 1 or 2 which you can calculate by unsigned level = (InputLevel * 3) / 32768 ;. You can then use that level value in a bit-shift (1 << level) to determine the LED to be set. Note that you had the low level set the high bit in your LED level indicator - that would require (4 >> level), which is somewhat clumsy if you were to ever increase the number of LEDs. It is easier to reverse the order of the GPIO in the BusOut object.
Additional advice:
Apply the rule of "minimal scope", localising variables to the minimum necessary scope (you have a number of unnecessary globals.
In "big-loop" scheduling, avoid thread delays during which useful work might otherwise be done. Your debounce delay unnecessarily determines the rate at which other work can be done in the loop. The advice would be different if you were polling the button and setting the LEDs in separate threads.
For example (not this is coded blind/untested - treat it as illustrative of the general principles - it may need debugging):
#include "mbed.h"
int main ()
{
static const unsigned DEBOUNCE_MS = 20u ;
static const unsigned NUMBER_OF_LEVELS = 3u ;
DigitalIn OnOffButton( PC_10 ) ;
DigitalOut OnOffLed( PC_0 ) ;
BusOut LevelIndicator( PA_4, PB_0, PC_1 ) ;
AnalogIn InputLevel( PA_5 ) ;
bool isOn = false ;
int previous_button_state = OnOffButton ;
std::uint64_t button_change_time = 0 ;
for(;;)
{
// If debounce time expired check for button state change
if( Kernel::get_ms_count() - button_change_time > DEBOUNCE_MS )
{
int current_button_state = OnOffButton ;
// If button state changed
if( current_button_state != previous_button_state )
{
// If button-down
if( current_button_state != 0 )
{
// Toggle isOn
isOn = !isOn ;
}
// Change of state and debounce update
previous_button_state = current_button_state ;
button_change_time = Kernel::get_ms_count() ;
}
}
// Set the LEDs depending on On/Off state and input level
if( isOn )
{
OnOffLed = 1 ;
// Set level indicator
LevelIndicator = 1 << (InputLevel.read_u16() * NUMBER_OF_LEVELS / 32768u) ;
}
else
{
// System inactive (Off)
LevelIndicator = 0 ;
OnOffLed = 0 ;
}
}
}
You might also consider separating out the button and indicator processing into separate functions to increase cohesion, minimise coupling, simplify testing and improve maintainability and comprehensibility.
#include "mbed.h"
void updateIndicators( bool isOn ) ;
bool getOnOffState() ;
int main ()
{
for(;;)
{
updateIndicators( getOnOffState() ) ;
}
}
bool getOnOffState()
{
static const unsigned DEBOUNCE_MS = 20u ;
static DigitalIn OnOffButton( PC_10 ) ;
static bool state = false ;
static int previous_button_state = OnOffButton ;
static std::uint64_t button_change_time = 0 ;
// If debounce time expired check for button state change
if( Kernel::get_ms_count() - button_change_time > DEBOUNCE_MS )
{
int current_button_state = OnOffButton ;
// If button state changed
if( current_button_state != previous_button_state )
{
// If button-down
if( current_button_state != 0 )
{
// Toggle isOn
state = !state ;
}
// Change of state and debounce update
previous_button_state = current_button_state ;
button_change_time = Kernel::get_ms_count() ;
}
}
return state ;
}
void updateIndicators( bool isOn )
{
static const unsigned NUMBER_OF_LEVELS = 3u ;
static DigitalOut OnOffLed( PC_0 ) ;
static BusOut LevelIndicator( PA_4, PB_0, PC_1 ) ;
static AnalogIn InputLevel( PA_5 ) ;
// Set the LEDs depending on On/Off state and input level
if( isOn )
{
OnOffLed = 1 ;
// Set level indicator
LevelIndicator = 1 << (InputLevel.read_u16() * NUMBER_OF_LEVELS / 32768u) ;
}
else
{
// System inactive (Off)
LevelIndicator = 0 ;
OnOffLed = 0 ;
}
}

reversed DOS game uncompression code: is that maybe a known compression method (RLE,...) or self-invented?

its a file uncompression routine from the 1990 DOS game Alpha Waves game loader (https://www.mobygames.com/game/continuum)
based on my https://github.com/LowLevelMahn/alpha_waves_loader reverse engineering project
first i've reversed the loader with IDA to a binary equal assemble-able asm code:
https://github.com/LowLevelMahn/alpha_waves_loader/blob/db422a5475a1939427b6379e688d23844535b7a9/ae.asm#L970
then i've translated the code to fake-assembler code (keeping the semantic but be able to use 32bit C/C++ code)
https://github.com/LowLevelMahn/alpha_waves_loader/blob/db422a5475a1939427b6379e688d23844535b7a9/read_some_file_sub_4/original_port.cpp#L9
the last step was a small unit test comparing the original fake-assembler code against a more and more cleanuped version of the algorithm
https://github.com/LowLevelMahn/alpha_waves_loader/blob/db422a5475a1939427b6379e688d23844535b7a9/read_some_file_sub_4/cleanup_port.cpp#L151
the reversed algorithm works with all compressed game data, got 100% coverage and a unit-test, the variable names are still a bit clumsy as i didn't understand the uncompresse algorithm fully
i've got a small (except the test data size) unit-test that got a nearly 100% coverage of the algorithm (execept the uncompress block case - that can be skipped here)
compiles standalone - out-of the box with a C++14 compiler VS2017+, gcc, clang tested
https://github.com/LowLevelMahn/alpha_waves_loader/blob/main/read_some_file_sub_4/example.cpp
online compile & debug-able at: https://onlinegdb.com/VjiONQjAu
can anyone tell me if that is some sort of standard (un)compression algorithm from the early times
or something completely self-invented by the game creator? (its dramatically reduced compared to the original asm but still not super-trivial)
the code seems to be recursive - flattened by using a stack while uncompression
void val_3_non_0( uint8_t*& uncompressed_, const tables_t& tables_, const uint8_t val_3_ )
{
struct stack_vals_t
{
uint8_t val_0{};
uint8_t val_1{};
};
std::stack<stack_vals_t> stack;
auto helper1 = [&stack, &tables_]( const uint8_t val_7_ ) {
stack.push( { val_7_, tables_.table2[val_7_] } );
return tables_.table1[val_7_];
};
auto helper2 = [&stack]( uint8_t* val_7_, uint8_t* val_4_ ) {
if( stack.empty() )
{
return true;
}
const stack_vals_t stack_val = stack.top();
stack.pop();
*val_7_ = stack_val.val_0;
*val_4_ = stack_val.val_1;
return false;
};
uint8_t val_7 = val_3_;
uint8_t val_4 = helper1( val_7 );
while( true )
{
const uint8_t val_5 = val_4;
const uint8_t val_6 = tables_.table3[val_5];
if( val_6 == 0 )
{
*uncompressed_++ = val_4;
if( helper2( &val_7, &val_4 ) )
{
return;
}
}
else if( val_7 > val_6 )
{
val_7 = val_6;
val_4 = helper1( val_7 );
}
else
{
val_4 = val_7;
val_7 = val_6;
assert( stack.size() >= 0 );
while( true )
{
val_7 = tables_.table4[val_7];
if( val_7 == 0 )
{
*uncompressed_++ = val_5;
if( helper2( &val_7, &val_4 ) )
{
return;
}
break;
}
else if( val_7 < val_4 )
{
val_4 = helper1( val_7 );
break;
}
// another run
}
}
}
}

Why does debounce code not work with 2 or more objects?

I have written a debounce class to debounce inputs.
The idea was that a state of a certain input may be ON, OFF, FALLING or RISING.
the object.debounceInputs() is to be called with a fixed interval
With the the function object.readInput() the correct state of the object could be read in. A FALLING or RISING state only lasts for 1 interval time (usually set at 20ms) and these states can only be read once.
Ofcourse I tested the software and it worked without flaw, now I started using the software in other projects and a peculiar bug came to light.
The software works perfectly fine... if you have just one input object. If you debounce more than 1 object, the inputs are affecting each other which should not be possible as every object uses private variables.
The source code:
#include "debounceClass.h"
Debounce::Debounce(unsigned char _pin) {
pinMode(_pin, INPUT_PULLUP); // take note I use a pull-up resistor by default
pin = _pin;
}
unsigned char Debounce::readInput() {
byte retValue = state;
if(state == RISING) state = ON; // take note I use a pull-up resistor
if(state == FALLING) state = OFF; // rising or falling may be returned only once
return retValue;
}
void Debounce::debounceInputs() {
static bool oldSample = false, statePrev = false;
bool newSample = digitalRead(pin);
if(newSample == oldSample) { // if the same state is detected atleast twice in 20ms...
if(newSample != statePrev) { // if a flank change occured return RISING or FALLING
statePrev = newSample ;
if(newSample) state = RISING;
else state = FALLING;
}
else { // or if there is no flank change return PRESSED or RELEASED
if(newSample) state = ON;
else state = OFF;
}
}
oldSample = newSample;
return 255;
}
The corresponding header file:
#include <Arduino.h>
#ifndef button_h
#define button_h
//#define
#define ON 9 // random numbers, RISING and FALLING are already defined in Arduino.h
#define OFF 10
class Debounce {
public:
Debounce(unsigned char _pin);
unsigned char readInput();
void debounceInputs();
private:
unsigned char state;
unsigned char pin;
};
#endif
I have had this bug with 2 separate projects, so the fault definitely lies in my Debounce class.
An example program to illustrate the program:
#include "debounceClass.h"
const int pin3 = 3 ;
const int pin4 = 4 ;
Debounce obj1( pin3 ) ;
Debounce obj2( pin4 ) ;
byte previousState1, previousState2;
unsigned long prevTime = 0, prevTime1 = 0, prevTime2 = 0;
void setup()
{
Serial.begin( 115200 ) ;
// CONSTRUCTOR OF OBJECTS SETS THE PINMODE TO INPUT_PULLUP
pinMode( pin3, OUTPUT ) ;
pinMode( pin4, OUTPUT ) ;
}
const int interval = 20, interval1 = 1000, interval2 = 2000;
void loop() {
unsigned long currTime = millis() ;
if( currTime > prevTime + interval ) {
prevTime = currTime ;
obj1.debounceInputs(); // comment one of these 2 out, and the other debounces perfectly
obj2.debounceInputs();
#define printState(x) case x: Serial.print(#x); break
byte state = obj1.readInput() ;
if( state != previousState1 ) {
previousState1 = state ;
Serial.print("state of obj1 = ") ;
switch ( state ) {
printState( ON ) ;
printState( OFF ) ;
printState( RISING ) ;
printState( FALLING ) ;
}
Serial.println();
}
state = obj2.readInput() ;
if( state != previousState2 ) {
previousState2 = state ;
Serial.print("state of obj2 = ") ;
switch ( state ) {
printState( ON ) ;
printState( OFF ) ;
printState( RISING ) ;
printState( FALLING ) ;
}
Serial.println();
}
}
if( currTime > prevTime1 + interval1 ) {
prevTime1 = currTime ;
digitalWrite( pin3, !digitalRead( pin3 ) );
}
if( currTime > prevTime2 + interval2 ) {
prevTime2 = currTime ;
digitalWrite( pin4, !digitalRead( pin4 ) );
}
}
This program automatically toggles both pins so you do not need physical inputs. If you comment out one of the indicated lines, you'll see that the other pin is debounced just fine. But when both pins are debounced the result is catastrophic. There is a weird link between the 2 objects which I cannot explain. I have reached a point at which I start doubting the compiler, so that was the moment I realized that I need to ask others.
Why is this happening and what did I do wrong here?
I found the problem.
I cannot use a static variable within a class method. These static variables are seen by all objects which caused the problem.
I moved the static variables to the private variable section

Embedded C counter between two values

Please help with my issue.
I am trying to avoid going out of the limit between 0 to 100 for the count up/down value in the program below;
I am using an 8051 microcontroller and 2x16 LCD to display a value between 0 and 100. when pressing the UP button the number increased by one, while when pressing down button it decreased by one.
my code keeps incrementing the value above 100 and less 0.
// This is a code in Embedded C written on MikroC compiler for 8051 microcontroller
// The microcontroller shall count up / down on the LCD when press up / down button.
unsigned int cntr=0; // counter value
char lcdv[6]; // Value to displau on lcd
sbit UP at P3.B7; // declare button UP at port 3 Bit 7.
sbit DN at P3.B6; // declare button UP at port 3 Bit 6.
// LCD module connections
sbit LCD_RS at P2_0_bit; // Declare LCD reset pin.
sbit LCD_EN at P2_1_bit; // Declare LCD Enable pin.
sbit LCD_D4 at P2_2_bit; // Declare LCD D4 pin.
sbit LCD_D5 at P2_3_bit; // Declare LCD D5 pin.
sbit LCD_D6 at P2_4_bit; // Declare LCD D6 pin.
sbit LCD_D7 at P2_5_bit; // Declare LCD D7 pin.
// End LCD module connections
char text[16]; // this is stored in RAM
void main() { // Main program
P3 = 255; // Configure PORT3 as input
Lcd_Init(); // Initialize LCD
cntr=0; // Starting counter value
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CURSOR_OFF);
while(1) {
while ((cntrset<=100)&&(cntrset>=0)) // Not sure how to limit Min and Max value.
{
wordTostr(cntrset,volset);
LCD_Out(2,1,volset);
if (UP==0)
cntrset ++;
while (UP==0);
if (DN==0)
cntrset=--;
while (DN==0);
}
}
}
if (UP==0 && cntrset < 100 ) cntrset++;
while (UP==0);
if (DN==0 cntrset > 0 ) cntrset--;
while (DN==0);
You may still have an issue with switch bounce causing a single press to result in the counter changing by more than one count. But that is a different question.
Regarding comment: If the increment is not by-one and the current value need not be a multiple of the increment, then it is easier to apply saturation instead:
if( UP == 0 ) cntrset += increment;
while (UP==0);
if( DN == 0 ) cntrset -= increment ;
while (DN==0);
if( cntrset < 0 ) cntrset = 0 ;
else if( cntrset > MAX_CNTRSET ) cntrset = MAX_CNTRSET ;
For that to work however you must change cntrset to signed int. If you'd rather not do that then (assuming 16 bit unsigned):
...
if( (cntrset & 0x8000u) != 0 ) cntrset = 0u ;
else if( cntrset > MAX_CNTRSET ) cntrset = MAX_CNTRSET ;