Issue with default stack size
shiftleftplusone opened this issue · comments
hi,
I just run into this issue with my Due:
the former code using cmaglie's Scheduler workes and still works fine,
but with this Scheduler the program freezes after
curlf(); sprintf(sbuf, " ...", curx); lcdprint(sbuf); delay(333); // <<<<<<<<<<<<<<
(last line in setup() ! )
what might be the reason?
/* Arduino Remote Console
* UART / Bluetooth HC-05 (master)
* Arduino Due
* IDE 1.6.12
*
* version RCsender0013
*
* change log:
* "heartbeat"
*
*/
#include <SPI.h>
#include <Scheduler.h>
// SPI header // |--|
// SPI pins Due // -----------| |------------
#define DUEMISO 74 // | RES 76_SCK 74_MISO |
#define DUEMOSI 75 // | -GND 75_MOSI Vc+5V |
#define DUESCK 76 // --------------------------
// SPI pins Mega
//#define MISO 50
//#define MOSI 51
//#define SCK 52
//=====================================================================================
// TFT LCD
//=====================================================================================
#define UTFT_SmallFont 8 // UTFT 8x10
#define UTFT_MediumFont 12 // UTFT ++
#define UTFT_BigFont 18 // UTFT +++
#define _SmallFont_ 1 // 9341 6x9
#define _MediumFont_ 2 // 9341 12x16
#define _BigFont_ 3 // 9341 18x23
int16_t LCDmaxX , LCDmaxY ; // display size
int16_t _curx_, _cury_, // last x,y cursor pos on TFT screen
_maxx_, _maxy_; // max. x,y cursor pos on TFT screen
// set LCD TFT type
int16_t LCDTYPE = -1;
#define _LCD1602_ 1 // LCD1602 Hitachi HD44780 driver <LiquidCrystal.h>
// http://www.arduino.cc/en/Tutorial/LiquidCrystal //
#define _UTFT_ 4 // Henning Karlsen UTFT 2.2-2.4" 220x176 - 320x240 lib
// http://henningkarlsen.com/electronics/library.php?id=51 //
#define _ILI9341_ 8 // https://github.com/adafruit/Adafruit_ILI9340
// https://github.com/adafruit/Adafruit-GFX-Library //
#define _ILI9341due_ 9 // ILI9341_due NEW lib by Marek Buriak
// http://marekburiak.github.io/ILI9341_due/ //
//--------------------------------------------------------------------------------------------------
#define tft_rst 0
#define tft_cs 48
#define tft_dc 49
#define _MEGAMISO_ 50
#define _MEGAMOSI_ 51
#define _MEGASCK_ 52
//=====================================================================================
// UTFT Henning Karlsen
//=====================================================================================
#include <UTFTQD.h> // patch for QD220A
// UTFT qdUTFT(Model, SDA=MOSI, SCL, CS, RESET, RS) // Due: 3 exposed SS pins: 4,10,52
// UTFT qdUTFT(QD220A, A2, A1, A5, A4, A3); // adjust model parameter and pins!
UTFT qdUTFT(QD220A, 23, 22, 26, 25, 24); //
// UTFT qdUTFT(QD220A, _MEGAMOSI_,_MEGASCK_, tft_cs, tft_rst, 47); // A0->Vc (LED), A4->BoardReset
extern uint8_t SmallFont[];
//=====================================================================================
// TFT Adafruit LIL9340/ILI9341
//=====================================================================================
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
Adafruit_ILI9341 tft = Adafruit_ILI9341(tft_cs, tft_dc, tft_rst);
//=====================================================================================
// TFT ILI9341_due // http://marekburiak.github.io/ILI9341_due/ //
//=====================================================================================
#include <ILI9341_due_config.h>
#include <ILI9341_due.h>
#include <SystemFont5x7.h>
ILI9341_due dtft = ILI9341_due(tft_cs, tft_dc);
// Color set
#define BLACK 0x0000
#define RED 0xF800
#define GREEN 0x07E0
//#define BLUE 0x001F
#define BLUE 0x102E
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define ORANGE 0xFD20
#define GREENYELLOW 0xAFE5
#define DARKGREEN 0x03E0
#define WHITE 0xFFFF
uint16_t color;
//--------------------------------------------------------------------------------------------------
#define lcdWhiteBlack() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor( 0, 0, 0);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK) ;} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(WHITE, BLACK) ;} \
}
#define lcdNormal() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor( 0, 0, 0);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK) ;} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(WHITE, BLACK) ;} \
}
#define lcdInvers() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor( 0, 0, 0); qdUTFT.setBackColor(255,255,255);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE) ;} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(BLACK, WHITE) ;} \
}
#define lcdWhiteRed() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor(255, 0, 0);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_WHITE, ILI9341_RED) ;} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(WHITE, RED) ;} \
}
#define lcdRedBlack() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor(255, 0, 0); qdUTFT.setBackColor( 0, 0, 0);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_RED, ILI9341_BLACK) ;} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(RED, BLACK) ;} \
}
#define lcdYellowBlue() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor(255,255, 0); qdUTFT.setBackColor( 64, 64, 64);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_YELLOW, ILI9341_BLUE);} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(YELLOW, BLUE);} \
}
int16_t fontwi= 8; // default
int16_t fonthi=10; // default
void putfonttype(uint8_t fsize) {
if(LCDTYPE==_UTFT_) {
fontwi= qdUTFT.getFontXsize();
fonthi= qdUTFT.getFontYsize();
}
else
if(LCDTYPE==_ILI9341_) {
if(fsize==_SmallFont_) { fontwi= 6; fonthi=9; } // 5x7 + overhead
else
if(fsize==_MediumFont_) { fontwi=12; fonthi=16; } // ?
else
if(fsize==_BigFont_) { fontwi=18; fonthi=23; } // ?
}
else
if(LCDTYPE==_ILI9341due_) {
if(fsize==_SmallFont_) { fontwi= 6; fonthi=9; } // 5x7 + overhead
}
_maxx_ = LCDmaxX / fontwi; // max number of letters x>>
_maxy_ = LCDmaxY / fonthi; // max number of letters y^^
}
void setlcdorient(int16_t orient) {
if(LCDTYPE==_ILI9341_) {
tft.setRotation(orient);
LCDmaxX=tft.width();
LCDmaxY=tft.height();
}
else
if(LCDTYPE==_ILI9341due_) {
dtft.setRotation( (iliRotation)orient);
LCDmaxX=dtft.width();
LCDmaxY=dtft.height();
}
}
void lcdcls() {
if(LCDTYPE==_UTFT_) { qdUTFT.clrScr(); }
else
if(LCDTYPE==_ILI9341_) { tft.fillScreen(ILI9341_BLACK); }
else
if(LCDTYPE==_ILI9341due_) { dtft.fillScreen(BLACK); }
_curx_ =0; _cury_ =0;
}
void curlf() {
_curx_=0;
if( _cury_ <=(LCDmaxY-10) ) _cury_+=fonthi;
else _cury_=0;
if(LCDTYPE==_ILI9341_) { tft.setCursor(0, _cury_); }
else
if(LCDTYPE==_ILI9341due_) { dtft.cursorToXY(0, _cury_); }
}
void curxy(int16_t x, int16_t y) {
_curx_ = x;
_cury_ = y;
if(LCDTYPE==_ILI9341_) {tft.setCursor(x, y); }
else
if(LCDTYPE==_ILI9341due_) {dtft.cursorToXY(x, y); }
}
void lcdprintxy(int16_t x, int16_t y, char * str) {
if(LCDTYPE==_UTFT_) {
qdUTFT.print(str,x,y);
_curx_=x+strlen(str)*fontwi;
_cury_=y;
}
else if(LCDTYPE==_ILI9341_) {
tft.setCursor(x,y);
tft.print(str);
_curx_=tft.getCursorX();
_cury_=tft.getCursorY();
}
else if(LCDTYPE==_ILI9341due_) {
dtft.cursorToXY(x,y);
dtft.printAt(str, x, y);
_curx_= x + strlen(str)*fontwi;
_cury_= y;
}
}
void lcdprint(char * str) {
if(LCDTYPE==_UTFT_) {
qdUTFT.print(str, _curx_, _cury_);
_curx_=_curx_+strlen(str)*fontwi;
}
else if(LCDTYPE==_ILI9341_) {
tft.setCursor(_curx_, _cury_);
tft.print(str);
_curx_=tft.getCursorX();
_cury_=tft.getCursorY();
}
else if(LCDTYPE==_ILI9341due_) {
dtft.cursorToXY(_curx_, _cury_);
dtft.printAt(str, _curx_, _cury_ );
_curx_ = _curx_ + (strlen(str)+3)*fontwi;
}
}
void initLCD(uint8_t orientation) { // 0,2==Portrait 1,3==Landscape
if(LCDTYPE==_UTFT_) {
qdUTFT.InitLCD(orientation%2);
LCDmaxX=qdUTFT.getDisplayXSize();
LCDmaxY=qdUTFT.getDisplayYSize();
qdUTFT.setFont(SmallFont);
putfonttype(UTFT_SmallFont);
}
else
if(LCDTYPE==_ILI9341_) {
tft.begin();
setlcdorient(orientation);
tft.setTextSize(_SmallFont_);
putfonttype(_SmallFont_);
}
else
if(LCDTYPE==_ILI9341due_) {
dtft.begin();
setlcdorient(orientation);
dtft.setFont(SystemFont5x7);
putfonttype(_SmallFont_);
}
}
//=====================================================================================
// UART DATA PACKAGES
//=====================================================================================
const uint8_t MSGSIZE = 64;
const uint32_t UARTclock = 115200;
uint8_t bsync= 0xff; // transmission control bytes: begin of msg signal : bsync=0xff (255)
volatile static uint8_t _heartbeat_ = 0;
#define MAXDIGPINS 16
#define MAXANALOG 9
#define MAXMOTORS 10
uint8_t sendbuf[MSGSIZE];
uint8_t recvbuf[MSGSIZE];
uint8_t sdispbuf[MSGSIZE];
uint8_t rdispbuf[MSGSIZE];
// message array setup:
#define SYNCSLOT 0 // start sync signal of this Msg: bsync=0xff (255)
#define CKSSLOT 1 // chksum this Msg
#define BYTE0 2 // byte 0 // byte: 8-bit => 8 digital bits 0-7
#define BYTE1 3 // byte 1 // byte: 8-bit => 8 digital bits 8-15
#define ENC0 4 // motorenc 0 // 10 encoders: 32-bit
#define ENC1 8 // motorenc 1
#define ENC2 12 // motorenc 2
#define ENC3 16 // motorenc 3
#define ENC4 20 // motorenc 4
#define ENC5 24 // motorenc 5
#define ENC6 28 // motorenc 6
#define ENC7 32 // motorenc 7
#define ENC8 36 // motorenc 8
#define ENC9 40 // motorenc 9
#define ANA0 44 // analog 0 // 9 analog: 16-bit
#define ANA1 46 // analog 1 // analog 0+1 = joystick for drive
#define ANA2 48 // analog 2
#define ANA3 50 // analog 3
#define ANA4 52 // analog 4
#define ANA5 54 // analog 5
#define ANA6 56 // analog 6
#define ANA7 58 // analog 7
#define ANA8 60 // analog 8
#define BYTE2 62 // byte 2 // byte: 8-bit => 8 digital bits 16-23
#define TERM 63 // terminating: heart beat signal
// motor runstates:
#define OUT_REGSTATE_NUL 0
#define OUT_REGSTATE_COAST 2
#define OUT_REGSTATE_BRAKE 3
#define OUT_REGSTATE_EMERG_STOP 5
#define OUT_REGSTATE_ON 8
#define OUT_REGSTATE_PIDIDLE 15
#define OUT_REGSTATE_PIDACTIVE 16
#define OUT_REGSTATE_PIDRELATIVE 17
#define OUT_REGSTATE_PIDABSOLUTE 18
#define OUT_REGSTATE_PIDHOLD 19
#define OUT_REGSTATE_PIDHOLDCLOSE 20
int8_t digval[MAXDIGPINS];
uint16_t digvalraw=0;
int16_t anaval[MAXANALOG];
int32_t motenc[MAXMOTORS], oldenc[MAXMOTORS] ;
// buffer for motor commands
uint8_t _motorstate_[7]; // 0: MOTORSLOT: MotNr
// 1: mot_runstate
// 2: pwm
// 3+4: mot enc_int16
// 5+6: mot enc_int32
//*************************************************************************************
//*************************************************************************************
// ARDUINO GPIO PIN SETUP
//*************************************************************************************
//*************************************************************************************
//=====================================================================================
// MOTORS
//=====================================================================================
// NA
//=====================================================================================
// analog Pins
//=====================================================================================
// A0, A1: Jstick_0 (remote tank propulsion drive)
//=====================================================================================
// digital Pins
//=====================================================================================
// 12 dPins R/W (free) : D02-D13
// 8 dPins R/W 16-23 : D22-D29
// 16 dPins R/W 0-15 : D30-D45
// 7 button pins: D30-D36
// 9 keypad pins: D37-D45
// 2 dPins (free) : D46-D47
// 2 TFT cs+dc pins: D48+D49
// SPI (Mega): D50-D52
// SPI (Due): D74-D76
// SD cs: D53
#define joystBtn_0 30
void setupdPins() {
int i;
for (i=22; i<29; ++i) {pinMode(i, INPUT_PULLUP);}
for (i=30; i<45; ++i) {pinMode(i, INPUT_PULLUP);}
}
//************************************************************************************
// bit and byte and pin operations
//************************************************************************************
// convert byte arrays to int
inline int16_t ByteArrayToInt16(uint8_t array[], uint8_t slot) {
return ((array[slot + 1] << 8) + (array[slot]));
}
inline long ByteArrayToInt32(uint8_t array[], uint8_t slot) {
return ( (array[slot+3]<<24) + (array[slot+2]<<16) + (array[slot+1]<<8) + array[slot] );
}
//------------------------------------------------------------------------------
// copy int to byte arrays
inline void Int8ToByteArray(int8_t vint8, uint8_t *array, uint8_t slot) {
memcpy(array+slot*sizeof(char), &vint8, sizeof(int8_t)); // copy int8 to array
}
inline void Int16ToByteArray(int16_t vint16, uint8_t *array, uint8_t slot) {
memcpy(array+slot*sizeof(char), &vint16, sizeof(int16_t)); // copy int16 to array
}
inline void Int32ToByteArray(int32_t vint32, uint8_t *array, uint8_t slot) {
memcpy(array+slot*sizeof(char), &vint32, sizeof(int32_t)); // copy int32 to array
}
inline void FloatToByteArray(float vfloat32, uint8_t *array, uint8_t slot) {
memcpy(array+slot*sizeof(char), &vfloat32, sizeof(float)); // copy float to array
}
//------------------------------------------------------------------------------
// read+write bits in numbers
/*
#define bitRead(source, bit) ( ((source) >> (bit)) & 0x01 )
#define bitSet (source, bit) ( (source) |= (1UL << (bit)) )
#define bitClear(source, bit) ( (source) &= ~(1UL << (bit)) )
#define bitWrite(source, bit, bitvalue) ( bitvalue ? bitSet(source, bit) : bitClear(source, bit) )
*/
//------------------------------------------------------------------------------------
int16_t toggleup(int16_t nr, int16_t max) {
if ( nr < (max - 1) ) ++nr;
else nr = 0;
return nr;
}
//------------------------------------------------------------------------------------
#define sensortouch(pinHIGH) !digitalRead(pinHIGH)
//------------------------------------------------------------------------------------
//*************************************************************************************
//*************************************************************************************
// UART TRANSMISSION CONTROL
//*************************************************************************************
//*************************************************************************************
//=====================================================================================
// CHECKSUM
//=====================================================================================
uint8_t calcchecksum(uint8_t array[]) {
int32_t sum=0;
for(int i=2; i<MSGSIZE; ++i) sum+=(array[i]);
return (sum & 0x00ff);
}
bool checksumOK(uint8_t array[]){
return (calcchecksum(array)==array[1]);
}
//=====================================================================================
// UART SEND/RECEIVE BUFFER
//=====================================================================================
// addToBuffer and receive function courtesy of chucktodd
bool addToBuffer( uint8_t buf[], uint8_t *cnt, uint16_t timeout){
bool inSync = *cnt>0;
unsigned long start=millis();
while((*cnt<MSGSIZE)&&(millis()-start<timeout)){
if(Serial1.available()){ // grab new char, test for sync char, if so start adding to buffer
buf[*cnt] = (uint8_t)Serial1.read();
if(inSync) *cnt += 1; // my origional *cnt++ was updating the pointer address, not
// the pointed to sendbuffer
else{
if(buf[*cnt]==0xFF){
inSync = true;
*cnt +=1;
}
}
}
}
return (*cnt==MSGSIZE);
}
//=====================================================================================
bool receive(uint8_t * buf, uint16_t timeout, uint8_t *cnt){ // by passing cnt in and out,
// i can timeout and still save a partial buffer, so a resync costs less (less data lost)
bool inSync=false;
unsigned long start=millis();
uint8_t * p; // pointer into buf for reSync operation
bool done=false;
do
{
done = addToBuffer(buf,cnt,timeout); // if this return false, a timeout has occured, and the while will exit.
if(done){ // do checksumOK test of buffer;
done=checksumOK(buf);
if (!done){// checksumOK failed, scan buffer for next sync char
p = (uint8_t*)memchr((buf+1),0xff,(MSGSIZE-1)); //forgot to skip the current sync at 0
if(p){ // found next sync char, shift buffer content, refill buffer
*cnt = MSGSIZE -(p-buf); // count of characters to salvage from this failure
memcpy(buf,p,*cnt); //cnt is now where the next character from Serial is stored!
}
else *cnt=0; // whole buffer is garbage
}
}
} while(!done&&(millis()-start<timeout));
return done; // if done then buf[] contains a sendbufid buffer, else a timeout occurred
}
//=====================================================================================
// acquire remote control values for send buffer
//=====================================================================================
int16_t analogTmpx=0, analogTmpy=0;
int16_t throttle, direction = 0; //throttle (Y axis) and direction (X axis)
int16_t leftMotor,leftMotorScaled = 0;
float leftMotorScale = 0;
int16_t rightMotor,rightMotorScaled = 0; //right Motor helper variables
float rightMotorScale = 0;
float maxMotorScale = 0; //holds the mixed output scaling factor
const byte joyst_0XA = A0; //Analog Jostick X axis // Joyst Anschluesse links
const byte joyst_0YA = A1; //Analog Jostick Y axis
//=====================================================================================
void getRCsendvalues()
{
char sbuf [128];
int8_t cbuf;
//aquire the analog input for Y and rescale the 0..1023 range to -255..255 range
analogTmpx = 1024 - analogRead(joyst_0YA);
throttle = (512-analogTmpx)/2;
//...and the same for X axis
analogTmpy = 1024- analogRead(joyst_0XA);
direction = (512-analogTmpy)/2;
sprintf(sbuf, "x:%6d, y:%6d ", analogTmpx, analogTmpy); Serial.print(sbuf);
//mix throttle and direction
leftMotor = -throttle + direction;
rightMotor = -throttle - direction;
//print the initial mix results
sprintf(sbuf, "LIN:%6d, RIN:%6d ", leftMotor, rightMotor); Serial.print(sbuf);
//calculate the scale of the results in comparision base 8 bit PWM resolution
leftMotorScale = leftMotor/255.0;
leftMotorScale = abs(leftMotorScale);
rightMotorScale = rightMotor/255.0;
rightMotorScale = abs(rightMotorScale);
sprintf(sbuf, "| LSCALE:%4.1f, RSCALE:%4.1f ", leftMotorScale, rightMotorScale); Serial.print(sbuf);
//choose the max scale value if it is above 1
maxMotorScale = max(leftMotorScale,rightMotorScale);
maxMotorScale = max(1,maxMotorScale);
//and apply it to the mixed values
leftMotorScaled = constrain(leftMotor/maxMotorScale,-255,255);
rightMotorScaled = constrain(rightMotor/maxMotorScale,-255,255);
sprintf(sbuf, "| LOUT:%6d, ROUT:%6d ", leftMotorScaled, rightMotorScaled); Serial.print(sbuf);
Serial.println("");
Int16ToByteArray(leftMotorScaled, sendbuf, ANA0);
Int16ToByteArray(rightMotorScaled, sendbuf, ANA1);
digval[0] = sensortouch(joystBtn_0);
bitWrite(cbuf, 0, digval[0]);
digval[1] = sensortouch( 31 ); // red Btn
bitWrite(cbuf, 1, digval[1]);
digval[2] = sensortouch( 32 ); // yellow Btn
bitWrite(cbuf, 2, digval[2]);
digval[3] = sensortouch( 33 ); // green Btn
bitWrite(cbuf, 3, digval[3]);
Int8ToByteArray( cbuf, sendbuf, BYTE0 );
delay(1);
}
//=====================================================================================
// L O O P
//=====================================================================================
void loop()
{
char sbuf[128], resOK=1;
static uint8_t cnt=0;
uint8_t cbuf[MSGSIZE], chk;
uint32_t xtime;
// send buffer
memset(sendbuf, 0, sizeof(sendbuf));
getRCsendvalues();
//TCP sync bytes
sendbuf[0]=bsync;
// heart beat
sendbuf[TERM] = _heartbeat_;
// checksum
sendbuf[1]=calcchecksum(sendbuf);
// Send value to the Rx Master
for(uint8_t i=0; i<MSGSIZE; i++) {
Serial1.write(sendbuf[i]);
}
memcpy(sdispbuf, sendbuf, sizeof(sendbuf));
// Receive buffer
memset(cbuf, 0, sizeof(cbuf));
// debug
resOK = receive ( cbuf, 10000,&cnt);
if( resOK ) { // byte 0 == syncbyte
cnt=0;
//displayvalues(60, "Received...:", cbuf);
chk=(byte)calcchecksum(cbuf);
memcpy(recvbuf, cbuf, sizeof(cbuf));
memcpy(rdispbuf, cbuf, sizeof(cbuf));
}
else _heartbeat_ = 0;
}
//=====================================================================================
// L O O P 2: Display
//=====================================================================================
void loop2() {
char sbuf[128];
sprintf(sbuf, "EKG: %3d", _heartbeat_ );
lcdprintxy(0, 20, sbuf);
sprintf(sbuf, "JSt_0 | Le=%4d | Ri=%4d | Btn=%1d |", leftMotorScaled, rightMotorScaled, digval[0] );
lcdprintxy(0, 40, sbuf);
sprintf(sbuf, "Btns: | RED=%1d | YEL=%1d | GRN=%1d |", digval[1], digval[2], digval[3] );
lcdprintxy(0, 50, sbuf);
yield();
delay(50);
yield();
}
//=====================================================================================
// L O O P 3: Heart Beat
//=====================================================================================
uint32_t stoptimer=0;
void loop3() {
if (millis()-stoptimer >= 100) {
++_heartbeat_;
stoptimer=millis();
if(_heartbeat_ >= 100) _heartbeat_ = 1; // always > 0
}
yield();
delay(10);
yield();
}
//*************************************************************************************
//*************************************************************************************
// setup
//*************************************************************************************
//*************************************************************************************
void setup() {
char sbuf[128];
int32_t i=0;
// Serial
Serial.begin(115200); // USB terminal
Serial1.begin(UARTclock); // RX-TX UART
while(Serial1.available()) Serial1.read(); // clear output buffer
// TFT LCD
Serial.println();
LCDTYPE = _ILI9341due_;
Serial.print("init LCD...");
initLCD(3);
Serial.println(" done."); lcdcls();
sprintf(sbuf, "LCD=%d wi%dxhi%d Font %dx%d",LCDTYPE,LCDmaxX,LCDmaxY,fontwi,fonthi);
Serial.println(sbuf);
Serial.println();
lcdcls(); lcdprint(sbuf);
setupdPins();
sprintf(sbuf, "dpins(): done.");
Serial.println(); Serial.println(sbuf);
curlf(); lcdprint(sbuf);
sprintf(sbuf, "Rx slave, BAUD= %ld", UARTclock );;
curlf(); lcdprint(sbuf);
// Add "loopX" to scheduling.
Scheduler.startLoop(loop2);
sprintf(sbuf, "MT display task started " );
curlf();
lcdprint(sbuf);
Scheduler.startLoop(loop3);
sprintf(sbuf, "MT heartbeat task started ");
curlf();
lcdprint(sbuf);
curlf();
sprintf(sbuf, "setup(): done.");
Serial.println(); Serial.println(sbuf);
curlf(); curlf(); lcdprint(sbuf);
sprintf(sbuf, "press JoystickButton 0 to start!");
Serial.println(); Serial.println(sbuf);
curlf(); curlf(); lcdprint(sbuf);
while( !sensortouch( joystBtn_0 ) ); while( sensortouch( joystBtn_0 ) );
lcdcls();
curlf(); sprintf(sbuf, " ...", _curx_); lcdprint(sbuf); delay(333); // <<<<<<<<<<<<<<
lcdcls();
}
I would check the stack size. This sketch uses a lot of stack.
well perhaps, but all required stack should be managed by the lib automatically (after all it's a Due!), and with cmaglie's lib it works nevertheless.
The only possible action to avoid this is using the same default stack size. Actually I would like to go the other direction and force explicit stack size.
well, some threads need more memory, some less, but all that should be maintained by the scheduler lib implicitely, or by a warning during runtime.
for using multithreading I actually wouldn't like to have to calculate all that by myself for either thread manually in advance.
How is this problem resolved by cmaglie?
And how does that work by POSIX pthread? Here I also never have to calculate stack size for either thread manually in advance
The arduino-library scheduler default stack is 1024 https://github.com/arduino-libraries/Scheduler/blob/master/src/Scheduler.h. This library uses a default value of 512.
There is a support function stack() that the running task can use to assert the available headroom.
POSIX threads on Linux uses Mbytes of thread stack. Embedded requires higher knowledge and skills.
so how to resolve this problem for my encountered issue in detail?
Finally my program cannot even be started at all and freezes prematurely...!
Start by changing the default stack size to 1024. After that use the stack() member function to determine how much stack is actually used. Trim the stack size accordingly but remember that the stack must always have room for any ISR.
how can I change the default stack size generally to 1024?
I never did things like that before :-/
(I also don't find a tutorial to your lib how to perform that)
... or do you mean: for each single task
Scheduler.start(taskSetup, taskLoop [,taskStackSize]);
here: 1024 for taskStackSize ??
but what is taskSetup then??
and do have to call
int bytes = Scheduler.stack();
from setup() or from loop() or inside of either taskLoop ?
...tbh, very weird.... :-/
I should also state that I normally take a manual debugging and lib-enhancement fee :)
Have you checked the stack size parameter?
I absolutely don't know how to do or to start to do anything to fix the problem because the program gets completely stuck and does nothing at all any more, and I do not understand anything of what you wrote about default stack or change default or check stack. There is no comprehensible tutorial and the given information is far too poor yet, unfortunately.
Using cmaglie's scheduler instead works out of the box, no hang-up and no complicated adjustments needed.
Perhaps you may wish to change my source code so that it works?
Start by explicitly adding the stack size to all task starts, e.g. Scheduler.startLoop(loop2, 1024)
. You might also need to use the Scheduler.begin(1024);
to force the main task stack size.
Please run the https://github.com/mikaelpatel/Arduino-Scheduler/blob/master/examples/SchedulerBlinkMax/SchedulerBlinkMax.ino example sketch to get an understanding of how the Scheduler.stack()
member function works. It is very enlightening.
Please see commit 95a0f81.
thank you, Now it's clear, I will do it this way:
Start by explicitly adding the stack size to all task starts, e.g. Scheduler.startLoop(loop2, 1024). You might also need to use the Scheduler.begin(1024); to force the main task stack size.
changing in the header file is no option because of platform-compatibility reasons.
Unfortunately don't understand the https://github.com/mikaelpatel/Arduino-Scheduler/blob/master/examples/SchedulerBlinkMax/SchedulerBlinkMax.ino example sketch at all, too many uncomprehensible letters... but it does not matter as far as Scheduler.startLoop(loop2, 1024) will work.
BTW, I have another DUE project with 1 task requiring about 40kB temporary memory for large arrays of double plus 8 smaller ones with about 1-10kB each; in that case the "big task" has to be started with
Scheduler.startLoop(bigThreadLoop, 40*1024) , and the other ones accordingly, correct?
also with
Scheduler.startLoop(loopX, 1024)
for all loops the programs freezes, nothing works.
Note that for loop() a 1024 cannot be specified.
I created a new loop1() for that as a substitute and started it with 1024,
nothing changed.
The program does not run any more and hangs up immediately after setup().
with cmaglie's Scheduler everything is fine though.
Try the code by yourself!
please reopen the issue as it is not resolved!
Download the updated version with the same default stack as the arduino-libraries/Scheduler. Please note that it is not enough to add the stack size to startLoop calls. You also need to give the main task a larger stack.
It is not loop() that is the issue it is the main setup().
I created a new loop1() for that as a substitute and started it with 1024,
nothing changed.
The program does not run any more and hangs up immediately after setup().
with cmaglie's Scheduler everything is fine though.
Try the code by yourself!
with the new downloaded version the program does not block after setup but then switches off completely a few seconds later, no screen output visible any more.
@shiftleftplusone As I suspected the default stack size was too small. Now the next step is to adjust the main task stack size further. The arduino-libraries/Scheduler main task does not have a 1K default. It is limited dynamically by the head end.
Please add the line Scheduler.begin(2048);
in beginning of your setup(). The 2048 is just a number to start with as 1024 was too small. The main task, loop(), in your sketch uses a lot of stack. You can later use the Scheduler.stack()
member function to determine the actual max stack size.
Please see https://github.com/mikaelpatel/Arduino-Scheduler/blob/master/Scheduler.h#L41.
but with cmaglie's Scheduler everything is fine, so the main task stack size can't be the reason why.
Or you will have to adjust all of cmaglie's settings to your version and re-adjust all of your default settings so that everything will be 100% compatible and will run out of the box.
For the moment there is too much manual adjusting for the end user, that is no fun at all.
Additionally, loop() does nothing any more.
it is just
void loop() {
}
All of the old loop is now in a new loop1().
Nevertheless, the issue remains the same, and cmaglie's scheduler runs fine with either version of loop or loop1.
again, there is no reason to close this issue because it is still unresolved
@shiftleftplusone Are you saying that loop() is empty???
yes.
It has to contain a yield() or a delay().
/* Arduino Remote Console
* UART / Bluetooth HC-05 (master)
* Arduino Due
* IDE 1.6.12
*
* version RCsender0013
*
* change log:
* "heartbeat"
*
*/
#include <SPI.h>
#include <Scheduler.h>
// SPI header // |--|
// SPI pins Due // -----------| |------------
#define DUEMISO 74 // | RES 76_SCK 74_MISO |
#define DUEMOSI 75 // | -GND 75_MOSI Vc+5V |
#define DUESCK 76 // --------------------------
// SPI pins Mega
//#define MISO 50
//#define MOSI 51
//#define SCK 52
//=====================================================================================
// TFT LCD
//=====================================================================================
#define UTFT_SmallFont 8 // UTFT 8x10
#define UTFT_MediumFont 12 // UTFT ++
#define UTFT_BigFont 18 // UTFT +++
#define _SmallFont_ 1 // 9341 6x9
#define _MediumFont_ 2 // 9341 12x16
#define _BigFont_ 3 // 9341 18x23
int16_t LCDmaxX , LCDmaxY ; // display size
int16_t _curx_, _cury_, // last x,y cursor pos on TFT screen
_maxx_, _maxy_; // max. x,y cursor pos on TFT screen
// set LCD TFT type
int16_t LCDTYPE = -1;
#define _LCD1602_ 1 // LCD1602 Hitachi HD44780 driver <LiquidCrystal.h>
// http://www.arduino.cc/en/Tutorial/LiquidCrystal //
#define _UTFT_ 4 // Henning Karlsen UTFT 2.2-2.4" 220x176 - 320x240 lib
// http://henningkarlsen.com/electronics/library.php?id=51 //
#define _ILI9341_ 8 // https://github.com/adafruit/Adafruit_ILI9340
// https://github.com/adafruit/Adafruit-GFX-Library //
#define _ILI9341due_ 9 // ILI9341_due NEW lib by Marek Buriak
// http://marekburiak.github.io/ILI9341_due/ //
//--------------------------------------------------------------------------------------------------
#define tft_rst 0
#define tft_cs 48
#define tft_dc 49
#define _MEGAMISO_ 50
#define _MEGAMOSI_ 51
#define _MEGASCK_ 52
//=====================================================================================
// UTFT Henning Karlsen
//=====================================================================================
#include <UTFTQD.h> // patch for QD220A
// UTFT qdUTFT(Model, SDA=MOSI, SCL, CS, RESET, RS) // Due: 3 exposed SS pins: 4,10,52
// UTFT qdUTFT(QD220A, A2, A1, A5, A4, A3); // adjust model parameter and pins!
UTFT qdUTFT(QD220A, 23, 22, 26, 25, 24); //
// UTFT qdUTFT(QD220A, _MEGAMOSI_,_MEGASCK_, tft_cs, tft_rst, 47); // A0->Vc (LED), A4->BoardReset
extern uint8_t SmallFont[];
//=====================================================================================
// TFT Adafruit LIL9340/ILI9341
//=====================================================================================
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
Adafruit_ILI9341 tft = Adafruit_ILI9341(tft_cs, tft_dc, tft_rst);
//=====================================================================================
// TFT ILI9341_due // http://marekburiak.github.io/ILI9341_due/ //
//=====================================================================================
#include <ILI9341_due_config.h>
#include <ILI9341_due.h>
#include <SystemFont5x7.h>
ILI9341_due dtft = ILI9341_due(tft_cs, tft_dc);
// Color set
#define BLACK 0x0000
#define RED 0xF800
#define GREEN 0x07E0
//#define BLUE 0x001F
#define BLUE 0x102E
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define ORANGE 0xFD20
#define GREENYELLOW 0xAFE5
#define DARKGREEN 0x03E0
#define WHITE 0xFFFF
uint16_t color;
//--------------------------------------------------------------------------------------------------
#define lcdWhiteBlack() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor( 0, 0, 0);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK) ;} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(WHITE, BLACK) ;} \
}
#define lcdNormal() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor( 0, 0, 0);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK) ;} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(WHITE, BLACK) ;} \
}
#define lcdInvers() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor( 0, 0, 0); qdUTFT.setBackColor(255,255,255);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE) ;} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(BLACK, WHITE) ;} \
}
#define lcdWhiteRed() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor(255, 0, 0);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_WHITE, ILI9341_RED) ;} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(WHITE, RED) ;} \
}
#define lcdRedBlack() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor(255, 0, 0); qdUTFT.setBackColor( 0, 0, 0);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_RED, ILI9341_BLACK) ;} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(RED, BLACK) ;} \
}
#define lcdYellowBlue() { \
if(LCDTYPE==_UTFT_) { qdUTFT.setColor(255,255, 0); qdUTFT.setBackColor( 64, 64, 64);} \
else if(LCDTYPE==_ILI9341_) { tft.setTextColor(ILI9341_YELLOW, ILI9341_BLUE);} \
else if(LCDTYPE==_ILI9341due_) { dtft.setTextColor(YELLOW, BLUE);} \
}
int16_t fontwi= 8; // default
int16_t fonthi=10; // default
void putfonttype(uint8_t fsize) {
if(LCDTYPE==_UTFT_) {
fontwi= qdUTFT.getFontXsize();
fonthi= qdUTFT.getFontYsize();
}
else
if(LCDTYPE==_ILI9341_) {
if(fsize==_SmallFont_) { fontwi= 6; fonthi=9; } // 5x7 + overhead
else
if(fsize==_MediumFont_) { fontwi=12; fonthi=16; } // ?
else
if(fsize==_BigFont_) { fontwi=18; fonthi=23; } // ?
}
else
if(LCDTYPE==_ILI9341due_) {
if(fsize==_SmallFont_) { fontwi= 6; fonthi=9; } // 5x7 + overhead
}
_maxx_ = LCDmaxX / fontwi; // max number of letters x>>
_maxy_ = LCDmaxY / fonthi; // max number of letters y^^
}
void setlcdorient(int16_t orient) {
if(LCDTYPE==_ILI9341_) {
tft.setRotation(orient);
LCDmaxX=tft.width();
LCDmaxY=tft.height();
}
else
if(LCDTYPE==_ILI9341due_) {
dtft.setRotation( (iliRotation)orient);
LCDmaxX=dtft.width();
LCDmaxY=dtft.height();
}
}
void lcdcls() {
if(LCDTYPE==_UTFT_) { qdUTFT.clrScr(); }
else
if(LCDTYPE==_ILI9341_) { tft.fillScreen(ILI9341_BLACK); }
else
if(LCDTYPE==_ILI9341due_) { dtft.fillScreen(BLACK); }
_curx_ =0; _cury_ =0;
}
void curlf() {
_curx_=0;
if( _cury_ <=(LCDmaxY-10) ) _cury_+=fonthi;
else _cury_=0;
if(LCDTYPE==_ILI9341_) { tft.setCursor(0, _cury_); }
else
if(LCDTYPE==_ILI9341due_) { dtft.cursorToXY(0, _cury_); }
}
void curxy(int16_t x, int16_t y) {
_curx_ = x;
_cury_ = y;
if(LCDTYPE==_ILI9341_) {tft.setCursor(x, y); }
else
if(LCDTYPE==_ILI9341due_) {dtft.cursorToXY(x, y); }
}
void lcdprintxy(int16_t x, int16_t y, char * str) {
if(LCDTYPE==_UTFT_) {
qdUTFT.print(str,x,y);
_curx_=x+strlen(str)*fontwi;
_cury_=y;
}
else if(LCDTYPE==_ILI9341_) {
tft.setCursor(x,y);
tft.print(str);
_curx_=tft.getCursorX();
_cury_=tft.getCursorY();
}
else if(LCDTYPE==_ILI9341due_) {
dtft.cursorToXY(x,y);
dtft.printAt(str, x, y);
_curx_= x + strlen(str)*fontwi;
_cury_= y;
}
}
void lcdprint(char * str) {
if(LCDTYPE==_UTFT_) {
qdUTFT.print(str, _curx_, _cury_);
_curx_=_curx_+strlen(str)*fontwi;
}
else if(LCDTYPE==_ILI9341_) {
tft.setCursor(_curx_, _cury_);
tft.print(str);
_curx_=tft.getCursorX();
_cury_=tft.getCursorY();
}
else if(LCDTYPE==_ILI9341due_) {
dtft.cursorToXY(_curx_, _cury_);
dtft.printAt(str, _curx_, _cury_ );
_curx_ = _curx_ + (strlen(str)+3)*fontwi;
}
}
void initLCD(uint8_t orientation) { // 0,2==Portrait 1,3==Landscape
if(LCDTYPE==_UTFT_) {
qdUTFT.InitLCD(orientation%2);
LCDmaxX=qdUTFT.getDisplayXSize();
LCDmaxY=qdUTFT.getDisplayYSize();
qdUTFT.setFont(SmallFont);
putfonttype(UTFT_SmallFont);
}
else
if(LCDTYPE==_ILI9341_) {
tft.begin();
setlcdorient(orientation);
tft.setTextSize(_SmallFont_);
putfonttype(_SmallFont_);
}
else
if(LCDTYPE==_ILI9341due_) {
dtft.begin();
setlcdorient(orientation);
dtft.setFont(SystemFont5x7);
putfonttype(_SmallFont_);
}
}
//=====================================================================================
// UART DATA PACKAGES
//=====================================================================================
const uint8_t MSGSIZE = 64;
const uint32_t UARTclock = 115200;
uint8_t bsync= 0xff; // transmission control bytes: begin of msg signal : bsync=0xff (255)
volatile static uint8_t _heartbeat_ = 0;
#define MAXDIGPINS 16
#define MAXANALOG 9
#define MAXMOTORS 10
uint8_t sendbuf[MSGSIZE];
uint8_t recvbuf[MSGSIZE];
uint8_t sdispbuf[MSGSIZE];
uint8_t rdispbuf[MSGSIZE];
// message array setup:
#define SYNCSLOT 0 // start sync signal of this Msg: bsync=0xff (255)
#define CKSSLOT 1 // chksum this Msg
#define BYTE0 2 // byte 0 // byte: 8-bit => 8 digital bits 0-7
#define BYTE1 3 // byte 1 // byte: 8-bit => 8 digital bits 8-15
#define ENC0 4 // motorenc 0 // 10 encoders: 32-bit
#define ENC1 8 // motorenc 1
#define ENC2 12 // motorenc 2
#define ENC3 16 // motorenc 3
#define ENC4 20 // motorenc 4
#define ENC5 24 // motorenc 5
#define ENC6 28 // motorenc 6
#define ENC7 32 // motorenc 7
#define ENC8 36 // motorenc 8
#define ENC9 40 // motorenc 9
#define ANA0 44 // analog 0 // 9 analog: 16-bit
#define ANA1 46 // analog 1 // analog 0+1 = joystick for drive
#define ANA2 48 // analog 2
#define ANA3 50 // analog 3
#define ANA4 52 // analog 4
#define ANA5 54 // analog 5
#define ANA6 56 // analog 6
#define ANA7 58 // analog 7
#define ANA8 60 // analog 8
#define BYTE2 62 // byte 2 // byte: 8-bit => 8 digital bits 16-23
#define TERM 63 // terminating: heart beat signal
// motor runstates:
#define OUT_REGSTATE_NUL 0
#define OUT_REGSTATE_COAST 2
#define OUT_REGSTATE_BRAKE 3
#define OUT_REGSTATE_EMERG_STOP 5
#define OUT_REGSTATE_ON 8
#define OUT_REGSTATE_PIDIDLE 15
#define OUT_REGSTATE_PIDACTIVE 16
#define OUT_REGSTATE_PIDRELATIVE 17
#define OUT_REGSTATE_PIDABSOLUTE 18
#define OUT_REGSTATE_PIDHOLD 19
#define OUT_REGSTATE_PIDHOLDCLOSE 20
int8_t digval[MAXDIGPINS];
uint16_t digvalraw=0;
int16_t anaval[MAXANALOG];
int32_t motenc[MAXMOTORS], oldenc[MAXMOTORS] ;
// buffer for motor commands
uint8_t _motorstate_[7]; // 0: MOTORSLOT: MotNr
// 1: mot_runstate
// 2: pwm
// 3+4: mot enc_int16
// 5+6: mot enc_int32
//*************************************************************************************
//*************************************************************************************
// ARDUINO GPIO PIN SETUP
//*************************************************************************************
//*************************************************************************************
//=====================================================================================
// MOTORS
//=====================================================================================
// NA
//=====================================================================================
// analog Pins
//=====================================================================================
// A0, A1: Jstick_0 (remote tank propulsion drive)
//=====================================================================================
// digital Pins
//=====================================================================================
// 12 dPins R/W (free) : D02-D13
// 8 dPins R/W 16-23 : D22-D29
// 16 dPins R/W 0-15 : D30-D45
// 7 button pins: D30-D36
// 9 keypad pins: D37-D45
// 2 dPins (free) : D46-D47
// 2 TFT cs+dc pins: D48+D49
// SPI (Mega): D50-D52
// SPI (Due): D74-D76
// SD cs: D53
#define joystBtn_0 30
void setupdPins() {
int i;
for (i=22; i<29; ++i) {pinMode(i, INPUT_PULLUP);}
for (i=30; i<45; ++i) {pinMode(i, INPUT_PULLUP);}
}
//************************************************************************************
// bit and byte and pin operations
//************************************************************************************
// convert byte arrays to int
inline int16_t ByteArrayToInt16(uint8_t array[], uint8_t slot) {
return ((array[slot + 1] << 8) + (array[slot]));
}
inline long ByteArrayToInt32(uint8_t array[], uint8_t slot) {
return ( (array[slot+3]<<24) + (array[slot+2]<<16) + (array[slot+1]<<8) + array[slot] );
}
//------------------------------------------------------------------------------
// copy int to byte arrays
inline void Int8ToByteArray(int8_t vint8, uint8_t *array, uint8_t slot) {
memcpy(array+slot*sizeof(char), &vint8, sizeof(int8_t)); // copy int8 to array
}
inline void Int16ToByteArray(int16_t vint16, uint8_t *array, uint8_t slot) {
memcpy(array+slot*sizeof(char), &vint16, sizeof(int16_t)); // copy int16 to array
}
inline void Int32ToByteArray(int32_t vint32, uint8_t *array, uint8_t slot) {
memcpy(array+slot*sizeof(char), &vint32, sizeof(int32_t)); // copy int32 to array
}
inline void FloatToByteArray(float vfloat32, uint8_t *array, uint8_t slot) {
memcpy(array+slot*sizeof(char), &vfloat32, sizeof(float)); // copy float to array
}
//------------------------------------------------------------------------------
// read+write bits in numbers
/*
#define bitRead(source, bit) ( ((source) >> (bit)) & 0x01 )
#define bitSet (source, bit) ( (source) |= (1UL << (bit)) )
#define bitClear(source, bit) ( (source) &= ~(1UL << (bit)) )
#define bitWrite(source, bit, bitvalue) ( bitvalue ? bitSet(source, bit) : bitClear(source, bit) )
*/
//------------------------------------------------------------------------------------
int16_t toggleup(int16_t nr, int16_t max) {
if ( nr < (max - 1) ) ++nr;
else nr = 0;
return nr;
}
//------------------------------------------------------------------------------------
#define sensortouch(pinHIGH) !digitalRead(pinHIGH)
//------------------------------------------------------------------------------------
//*************************************************************************************
//*************************************************************************************
// UART TRANSMISSION CONTROL
//*************************************************************************************
//*************************************************************************************
//=====================================================================================
// CHECKSUM
//=====================================================================================
uint8_t calcchecksum(uint8_t array[]) {
int32_t sum=0;
for(int i=2; i<MSGSIZE; ++i) sum+=(array[i]);
return (sum & 0x00ff);
}
bool checksumOK(uint8_t array[]){
return (calcchecksum(array)==array[1]);
}
//=====================================================================================
// UART SEND/RECEIVE BUFFER
//=====================================================================================
// addToBuffer and receive function courtesy of chucktodd
bool addToBuffer( uint8_t buf[], uint8_t *cnt, uint16_t timeout){
bool inSync = *cnt>0;
unsigned long start=millis();
while((*cnt<MSGSIZE)&&(millis()-start<timeout)){
if(Serial1.available()){ // grab new char, test for sync char, if so start adding to buffer
buf[*cnt] = (uint8_t)Serial1.read();
if(inSync) *cnt += 1; // my origional *cnt++ was updating the pointer address, not
// the pointed to sendbuffer
else{
if(buf[*cnt]==0xFF){
inSync = true;
*cnt +=1;
}
}
}
}
return (*cnt==MSGSIZE);
}
//=====================================================================================
bool receive(uint8_t * buf, uint16_t timeout, uint8_t *cnt){ // by passing cnt in and out,
// i can timeout and still save a partial buffer, so a resync costs less (less data lost)
bool inSync=false;
unsigned long start=millis();
uint8_t * p; // pointer into buf for reSync operation
bool done=false;
do
{
done = addToBuffer(buf,cnt,timeout); // if this return false, a timeout has occured, and the while will exit.
if(done){ // do checksumOK test of buffer;
done=checksumOK(buf);
if (!done){// checksumOK failed, scan buffer for next sync char
p = (uint8_t*)memchr((buf+1),0xff,(MSGSIZE-1)); //forgot to skip the current sync at 0
if(p){ // found next sync char, shift buffer content, refill buffer
*cnt = MSGSIZE -(p-buf); // count of characters to salvage from this failure
memcpy(buf,p,*cnt); //cnt is now where the next character from Serial is stored!
}
else *cnt=0; // whole buffer is garbage
}
}
} while(!done&&(millis()-start<timeout));
return done; // if done then buf[] contains a sendbufid buffer, else a timeout occurred
}
//=====================================================================================
// acquire remote control values for send buffer
//=====================================================================================
int16_t analogTmpx=0, analogTmpy=0;
int16_t throttle, direction = 0; //throttle (Y axis) and direction (X axis)
int16_t leftMotor,leftMotorScaled = 0;
float leftMotorScale = 0;
int16_t rightMotor,rightMotorScaled = 0; //right Motor helper variables
float rightMotorScale = 0;
float maxMotorScale = 0; //holds the mixed output scaling factor
const byte joyst_0XA = A0; //Analog Jostick X axis // Joyst Anschluesse links
const byte joyst_0YA = A1; //Analog Jostick Y axis
//=====================================================================================
void getRCsendvalues()
{
char sbuf [128];
int8_t cbuf;
//aquire the analog input for Y and rescale the 0..1023 range to -255..255 range
analogTmpx = 1024 - analogRead(joyst_0YA);
throttle = (512-analogTmpx)/2;
//...and the same for X axis
analogTmpy = 1024- analogRead(joyst_0XA);
direction = (512-analogTmpy)/2;
sprintf(sbuf, "x:%6d, y:%6d ", analogTmpx, analogTmpy); Serial.print(sbuf);
//mix throttle and direction
leftMotor = -throttle + direction;
rightMotor = -throttle - direction;
//print the initial mix results
sprintf(sbuf, "LIN:%6d, RIN:%6d ", leftMotor, rightMotor); Serial.print(sbuf);
//calculate the scale of the results in comparision base 8 bit PWM resolution
leftMotorScale = leftMotor/255.0;
leftMotorScale = abs(leftMotorScale);
rightMotorScale = rightMotor/255.0;
rightMotorScale = abs(rightMotorScale);
sprintf(sbuf, "| LSCALE:%4.1f, RSCALE:%4.1f ", leftMotorScale, rightMotorScale); Serial.print(sbuf);
//choose the max scale value if it is above 1
maxMotorScale = max(leftMotorScale,rightMotorScale);
maxMotorScale = max(1,maxMotorScale);
//and apply it to the mixed values
leftMotorScaled = constrain(leftMotor/maxMotorScale,-255,255);
rightMotorScaled = constrain(rightMotor/maxMotorScale,-255,255);
sprintf(sbuf, "| LOUT:%6d, ROUT:%6d ", leftMotorScaled, rightMotorScaled); Serial.print(sbuf);
Serial.println("");
Int16ToByteArray(leftMotorScaled, sendbuf, ANA0);
Int16ToByteArray(rightMotorScaled, sendbuf, ANA1);
digval[0] = sensortouch(joystBtn_0);
bitWrite(cbuf, 0, digval[0]);
digval[1] = sensortouch( 31 ); // red Btn
bitWrite(cbuf, 1, digval[1]);
digval[2] = sensortouch( 32 ); // yellow Btn
bitWrite(cbuf, 2, digval[2]);
digval[3] = sensortouch( 33 ); // green Btn
bitWrite(cbuf, 3, digval[3]);
Int8ToByteArray( cbuf, sendbuf, BYTE0 );
delay(1);
}
//=====================================================================================
// L O O P 1 : UART
//=====================================================================================
void loop1()
{
char sbuf[128], resOK=1;
static uint8_t cnt=0;
uint8_t cbuf[MSGSIZE], chk;
uint32_t xtime;
// send to Tx master
memset(sendbuf, 0, sizeof(sendbuf));
getRCsendvalues();
//TCP sync bytes
sendbuf[0]=bsync;
// heart beat
sendbuf[TERM] = _heartbeat_;
// checksum
sendbuf[1]=calcchecksum(sendbuf);
// Send value to the Rx Master
for(uint8_t i=0; i<MSGSIZE; i++) {
Serial1.write(sendbuf[i]);
}
memcpy(sdispbuf, sendbuf, sizeof(sendbuf));
// Receive fromTx master
memset(cbuf, 0, sizeof(cbuf));
// debug
resOK = receive ( cbuf, 10000,&cnt);
if( resOK ) { // byte 0 == syncbyte
cnt=0;
//displayvalues(60, "Received...:", cbuf);
chk=(byte)calcchecksum(cbuf);
memcpy(recvbuf, cbuf, sizeof(cbuf));
memcpy(rdispbuf, cbuf, sizeof(cbuf));
}
else _heartbeat_ = 0;
}
//=====================================================================================
// L O O P 2: Display
//=====================================================================================
void loop2() {
char sbuf[128];
sprintf(sbuf, "EKG: %3d", _heartbeat_ );
lcdprintxy(0, 20, sbuf);
sprintf(sbuf, "JSt_0 | Le=%4d | Ri=%4d | Btn=%1d |", leftMotorScaled, rightMotorScaled, digval[0] );
lcdprintxy(0, 40, sbuf);
sprintf(sbuf, "Btns: | RED=%1d | YEL=%1d | GRN=%1d |", digval[1], digval[2], digval[3] );
lcdprintxy(0, 50, sbuf);
yield();
delay(50);
yield();
}
//=====================================================================================
// L O O P 3: Heart Beat
//=====================================================================================
uint32_t stoptimer=0;
void loop3() {
if (millis()-stoptimer >= 100) {
++_heartbeat_;
stoptimer=millis();
if(_heartbeat_ >= 100) _heartbeat_ = 1; // always > 0
}
yield();
delay(10);
yield();
}
//*************************************************************************************
//*************************************************************************************
// setup
//*************************************************************************************
//*************************************************************************************
void setup() {
char sbuf[128];
int32_t i=0;
// Serial
Serial.begin(115200); // USB terminal
Serial1.begin(UARTclock); // RX-TX UART
while(Serial1.available()) Serial1.read(); // clear output buffer
// TFT LCD
Serial.println();
LCDTYPE = _ILI9341due_;
Serial.print("init LCD...");
initLCD(3);
Serial.println(" done."); lcdcls();
sprintf(sbuf, "LCD=%d wi%dxhi%d Font %dx%d",LCDTYPE,LCDmaxX,LCDmaxY,fontwi,fonthi);
Serial.println(sbuf);
Serial.println();
lcdcls(); lcdprint(sbuf);
setupdPins();
sprintf(sbuf, "dpins(): done.");
Serial.println(); Serial.println(sbuf);
curlf(); lcdprint(sbuf);
sprintf(sbuf, "Rx slave, BAUD= %ld", UARTclock );;
curlf(); lcdprint(sbuf);
// Add "loopX" to scheduling.
Scheduler.start(loop1);
sprintf(sbuf, "UART task started " );
Scheduler.start(loop2);
sprintf(sbuf, "MT display task started " );
curlf();
lcdprint(sbuf);
Scheduler.start(loop3);
sprintf(sbuf, "MT heartbeat task started ");
curlf();
lcdprint(sbuf);
curlf();
sprintf(sbuf, "setup(): done.");
Serial.println(); Serial.println(sbuf);
curlf(); curlf(); lcdprint(sbuf);
sprintf(sbuf, "press JoystickButton 0 to start!");
Serial.println(); Serial.println(sbuf);
curlf(); curlf(); lcdprint(sbuf);
while( !sensortouch( joystBtn_0 ) ); while( sensortouch( joystBtn_0 ) );
lcdcls();
curlf(); sprintf(sbuf, " ...", _curx_); lcdprint(sbuf); delay(333); // <<<<<<<<<<<<<<
lcdcls();
}
void loop() {
yield(); // added, but the issue remains: termates prematurely !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
//====
So there is your error :)
no one told that before, and again:
cmaglie's version is fine for either loop or loop1
I think you must adjust all your defaults to make it work out of the box, like cmaglie did.
Thanks for your suggestion.
also Scheduler. start does not work any more,
and also with yield() in loop() the program still terminates prematurely.
So this issue is not resolved at all, no reason to close it.
Please reopen it again.
I am sorry but I cannot help you with that. This issue is now locked and will remain closed.