Go Down

Topic: [SOLVED] Arduino Crashing on digitalWrite in external .cpp file (Read 222 times) previous topic - next topic

XaveJohnson

Edit: Solution is found in post #3 and #4 with the buggy code in post #2
Lesson: Do not define your own digitalWrite function and ask yourself why digitalWrite does not work.

Solution: Rename your custom function to digital_write(); or something else.
I am looking for differences in digitalWrite in a libary (with Arduino.h included) to digitalWrite in the Sketch itself. If you suspect the mistake somwhere else, just tell me.

My script fails in following function in an self-written libary for Shift registers. (My code is huge so i  created an abstraction able to reproduce the error)

.ino file: (only exists to spot the error)

Code: [Select]
#include <extendedoutputs.h>


ExtendedOutput exout(11, 12, 13);
//Not working code:
#define latch_pin 11
#define data_pin 12
#define clock_pin 13
byte out = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:

Serial.println("before internal function");
delay(2000);
senddata();


Serial.println("after internal function");
delay(2000);
exout.send();

}


void senddata(){
  Serial.println("Internal, Pre For");
  delay(2000);
  
  digitalWrite(latch_pin, 1);
  for(int i = 0; i<8; i++){
    Serial.println("Internal For");
    delay(2000);
    digitalWrite(clock_pin, 0);
    digitalWrite(data_pin, out & (1<<(7-i)));
    digitalWrite(clock_pin, 1);
  }
  digitalWrite(latch_pin, 1);
  digitalWrite(clock_pin, 0);
  digitalWrite(latch_pin, 0);
}


extendedoutputs.h file (shortened, still able to reproduce the error  EDIT:: Aparently not able to reproduce the error! Error code in post #2)
Code: [Select]
#include <Arduino.h>

class ExtendedOutput{
public:
        ExtendedOutput(int _latch, int _data, int _clock);
        void send();
private:
 byte out;
 const int data_pin;
 const int clock_pin;
 const int latch_pin;
};


extendedoutputs.cpp file (shortened as well)
Code: [Select]
#include <extendedoutputs.h>

ExtendedOutput::ExtendedOutput(int _latch, int _data, int _clock):data_pin(_data), clock_pin(_clock), latch_pin(_latch){}

void ExtendedOutput::send(){
 Serial.println("External, Pre for");
 Serial.println(this->latch_pin);
 delay(2000);
 
 digitalWrite(this->latch_pin, 1);
 for(int i = 0; i<8; i++){
 Serial.println("External For");
 delay(2000);
 digitalWrite(this->clock_pin, 0);
 digitalWrite(this->data_pin, !!(out & (1<<(7-i))));
 digitalWrite(this->clock_pin, 1);
 }
 digitalWrite(this->latch_pin, 1);
 digitalWrite(this->clock_pin, 0);
 digitalWrite(this->latch_pin, 0);
}

The Delays are there so that the arduino prints the Serial.prints before crashing.


Serial Monitor reveals the bug:
Code: [Select]
before internal function
Internal, Pre ForInternal For
Internal For
Internal For
Internal For
Internal For
Internal For
Internal For
Internal For
after internal function
External, Pre for11
External, Pre for11
External, Pre for11
External, Pre for11

//Goes on like this 20 times, then reboots
//should be pre For once and 8 times For alone. Internal stands for the function defined in the .ino and external for the function in the .cpp


So it crashes on the first digitalWrite() in the external function, and restarts that function (also why does it do that?)
The other funtion works fine
Thanks for reading until here ;)

blh64

That output did not come from the code you posted (similar).  Here is the output I get:
Code: [Select]

before internal function
Internal, Pre For
Internal For
Internal For
Internal For
Internal For
Internal For
Internal For
Internal For
Internal For
after internal function
External, Pre for
11
Internal For
Internal For
Internal For
Internal For
Internal For
Internal For
Internal For
Internal For
before internal function
Internal, Pre For
Internal For
Internal For
Internal For
Internal For
Internal For
Internal For
Internal For
Internal For
after internal function
External, Pre for
11
Internal For
Internal For
...


I do not have anything connected to any of the pins.  I suspect that you do have something tied to those pins and you may be pulling your power supply down which will reset the chip.  Disconnect all the pins and give it a try.

XaveJohnson

#2
Sep 16, 2018, 10:15 pm Last Edit: Sep 16, 2018, 10:53 pm by XaveJohnson
Thank you for your answer blh64.
I tested it with and without peripherals. Failed both times.
Also i do not understand why the internal function works, but the external doesent. Thats why i never thought the error would be in the hardware

HOWEVER I did not use the shortened version of my Libary. With this particular shortened version i posted, no errors occured. Apologies for not testing exactly that :smiley-roll-blue:

So here is my Full Libary, i recommend to just copy and paste it in. I could not find any significant Difference in the real Libary to the shortened version. The send() function is the same.

extendedoutputs.h: (Edit: the bug is the self defined digitalWrite function)
Code: [Select]
#ifndef EXTENDED_OUTPUTS_HEADER
#define EXTENDED_OUTPUTS_HEADER
#include <Arduino.h>



class ExtendedOutput{
public:
 ExtendedOutput(int _latch, int _data, int _clock);
 //POST:: Pin is immediately set. requires some time
 void digitalWrite(int pin, bool value);
 //POST:: sets a pin in the sendbyte. Only has an effect when it is sent, by caling send()
 void digitalSet(int pin, bool value);
 //POST:: sends the outbyte
 void send();
 //POST:: Sets sendbyte for the stepper to do a step in the given direction. only executed when send is called
 void setStep(bool dir);
 //POST:: Steper motor instantly does a step in asked direction
 void step(bool dir);
 
 unsigned int current_step = 0;
 int steps_needed = 100;
private:
 byte out;
 const int data_pin;
 const int clock_pin;
 const int latch_pin;
 //Stepper Motor
 const byte steps[8] = {0b1000,0b1100,0b0100,0b0110,0b0010,0b0011,0b0001,0b1001};
 
};
#endif




Code: [Select]
#include <extendedoutputs.h>
#include <Arduino.h>

ExtendedOutput::ExtendedOutput(int _latch, int _data, int _clock):data_pin(_data), clock_pin(_clock), latch_pin(_latch){}


void ExtendedOutput::setStep(bool dir){
 if(dir){
 this->current_step++;
 }else{
 this->current_step--;
 }
 for(int i = 0; i<4; i++){
 digitalSet(i, this->steps[current_step%8] & (1<<i));
 }
}
void ExtendedOutput::step(bool dir){
 setStep(dir);
 this->send();
}

/*----------------EDIT: ------------
The Bug is following function. Intended to closely resemble the original digitalWrite Function
it was choosen by the compiler to be the digitalWrite function i wanted to use in the send(); function,
so it would indefinitely call itself. send()->digitalWrite->send()->digitalWrite->......
*/

void ExtendedOutput::digitalWrite(int pin, bool value){
 digitalSet(pin, value);
 send();
}
void ExtendedOutput::digitalSet(int pin, bool value){
 if (pin > 7 || pin < 0) return;
 out ^= (-(unsigned byte)value ^ out) & (1 << pin);
}


void ExtendedOutput::send(){
 Serial.println("External, Pre for");
 Serial.println(this->latch_pin);
 delay(2000);
 
 digitalWrite(this->latch_pin, 1);
 for(int i = 0; i<8; i++){
 Serial.println("External For");
 delay(2000);
 digitalWrite(this->clock_pin, 0);
 digitalWrite(this->data_pin, !!(out & (1<<(7-i))));
 digitalWrite(this->clock_pin, 1);
 }
 digitalWrite(this->latch_pin, 1);
 digitalWrite(this->clock_pin, 0);
 digitalWrite(this->latch_pin, 0);
}


Probably, if we discover the difference, we can pinpoint the error.

Coding Badly

#3
Sep 16, 2018, 10:31 pm Last Edit: Sep 16, 2018, 10:32 pm by Coding Badly

Infinite recursion.  digitalWrite was a very bad choice for a method name.


XaveJohnson

#4
Sep 16, 2018, 10:39 pm Last Edit: Sep 16, 2018, 11:02 pm by XaveJohnson
Yes just found it myself........................

Hahaha now i can laugh on myself.
:smiley-mr-green:


Thank you CodingBadly for finding it tough!!!
It took me 5 hours looking at the code to find it. ~5 minutes for you.  :o

For later Readers
In my class i defined my own digitalWrite fuction which was prefered over the Arduino digitalWrite function.


I really tried to make my Extended output resemble a normal digital write just to shift register pins. This was my Mistake.

XaveJohnson

Just because i am curious:
Is there a way to tell the compiler when i want to use the standard DigitalWrite function and when i want to use the memberfunction?

AWOL

"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

Coding Badly


And/or the global scope resolution operator?

But, the better choice is to stop trying to overload the digitalWrite function.


XaveJohnson

Ok thank you.

So ::digitalWrite would give me the standard Function, even if i had a member function called the same.
(Dont worry i changed the name of the function ;) )


Go Up