Strange Boolean problem

Hi,
In my sketch I'm using several boolean variables. When I run the program it doesn't seem to respond to the state of the boolean. But when I include the statement Serial.println(boolean name) in the loop, the booleans suddenly seem to work, no matter which boolean I include in the Serial.println statement.
Anyone has a suggestion? B.T.W. the compiler does not report any errors.

Hello,

could you share with us your code? Would be helpful.

I imagine the problem lies in the code you haven't shown us.

Yes I understand but the code is more than 600 lines.... I can post the loop part, about 200 lines?

Please show all the code between code tags (use the <code/> button).

Post the whole sketch. You do not know which part is causing the problem and nor do we

OK, her it comes...

/*
  A part of this program is taken from Jason Mildrum, NT7S.
  All extra functions are written by me, Rob Engberts PA0RWE

  References:
  http://nt7s.com/
  http://sq9nje.pl/
  http://ak2b.blogspot.com/
  http://pa0rwe.nl/?page_id=804

 *  SI5351_VFO control program for Arduino NANO
 *  Copyright PA0RWE Rob Engberts
 *  
 *  Using the old Si5351 library by Jason Mildrun nt7s
 *
 *  Functions:
 *  - CLK0 - Tx frequency = Display frequency
 *  - CLK1 - Rx / RIT frequency = Tx +/- BFO (upper- or lower mixing)
 *           When RIT active, RIT frequency is displayed and is tunable.
 *           When RIT is inactive Rx = Tx +/- BFO
 *  - CLK2 - BFO frequency, tunable
 *
 *  - Stepsize:  select (pushbutton)
 *  - Calibrate: (pushbutton) calculates difference between X-tal and measured
 *               x-tal frequency, to correct x-tal frequency.
 *  - Selection: (pushbutton) Switch between TRx and BFO mode
 *  - RITswitch: tunable Rx frequency, while Tx frequency not changed
 *  
 *  Si5351 settings: I2C address is in the .h file
 *                   X-tal freq is in the .h file but set in line 354
 *
***************************************************************************
 *  02-04-2015   1.0    Start building program based on the PIC version
 *  18-06-2019   1.1    Extend frequency range to 10 KHz down
 *                      Update frequency display. Added 'MHz' and 'KHz'
 *                      Set max frequency to 100 MHz.
 *  21-06-2020   2.0    Changed text BFO to IF
 *                      Changed bfo_t => vfo_if, vfo_t => vfo_hf, vfo_r => vfo_lo
 *                      Make possible to use the vfo for upper or lower mixing
 *                        by using a #define statement (upper or lower)
 *                      Store of actual frequency after 5 seconds of not tuning  
 *                      Set Hz digit of frequency at start to zero (0)
 *                      Stepsize was not saved. Repaired
 *  06-04-2021   3.0    Added backward stepsize by pressing stepsize button longer                      
 *  06-08-2022   3.1    DG1KPN has changed the lower frequency to 8kHz. 
 *                      but on the display starting at 9.999kHz the number is shifted 
 *                      down covering the "Step" The same thing happens if you select 
 *                      an IF below 10kHz for a direct conversion receiver.
 *                      This all is repaired in this version.
 *  02-04-2023   4.0    Completely rewritten because strange errors.... 

***************************************************************************
*  Includes
**************************************************************************/
#include <Rotary.h>
#include <RWE_si5351.h> 
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>

/**************************************************************************
*  Define Upper / Lower mixing  (Remark // if not true)
**************************************************************************/
#define UPPER
//#define LOWER

/**************************************************************************
*  (Pin) Definitions
**************************************************************************/
#define ENCODER_A     2       // Encoder pin A INT0/PCINT18 D2
#define ENCODER_B     3       // Encoder pin B INT1/PCINT19 D3
#define ENCODER_BTN   4       // Encoder pushbutton D4
#define CALIBRBTN     5       // Calibrate
#define RITSWITCH     6       // RIT Switch
#define TXSWITCH     7       // Select TRx or BFO
#define OLED_RESET    -1      // OLED reset
//      I2C-SDA       A4      // I2C-SDA
//      I2C-SCL       A5      // I2C-SCL

#define F_MIN           1000UL       // Lower frequency limit   1 KHz
#define F_MAX      100000000UL       // Upper frequency limit 100 MHz

/**************************************************************************
*  EEPROM data locations 
**************************************************************************/
#define EE_SAVED_RADIX  0   // Stepsize pointer
#define EE_SAVED_AFREQ  4   // Actual Tx Frequency (CLK0)
#define EE_SAVED_BFREQ  8   // BFO (IF) Frequency  (CLK2)
#define EE_SAVED_XFREQ  12  // X-tal frequency  (25 or 27 MHz)
#define EE_SAVED_OFSET  16  // store correction
#define EE_SAVED_CALBR  20  // calibrated indicator

Adafruit_SSD1306 display(OLED_RESET);
Si5351 si5351;
Rotary r = Rotary(ENCODER_A, ENCODER_B);

/**************************************************************************
*  Declarations
**************************************************************************/
volatile uint32_t vfo_if =  900000000ULL / SI5351_FREQ_MULT;   // CLK0 start IF
volatile uint32_t vfo_hf = 1420000000ULL / SI5351_FREQ_MULT;   // CLK2 start Tx freq
volatile uint32_t vfo_lo = vfo_hf - vfo_if;                    // CLK1 start Rx freq
volatile uint32_t vfo_s = vfo_hf;                              // Saved for RIT
uint32_t vco_c = 0;                                            // X-tal correction factor
uint32_t xt_freq;
uint32_t test = 0;
uint32_t radix = 100ULL, old_radix = 100ULL;                   //start step size
int  act_clk = 0, disp_txt = 0;
bool changed_f = false, stepflag = false, calflag = false, modeflag = false, ritset = false;
bool kalibrate = false, actupdt = false;


unsigned long startTime;
unsigned long duration;
unsigned long startMillis = 0;

/**************************************/
/* Interrupt service routine for      */
/* encoder frequency change           */
/**************************************/
ISR(PCINT2_vect) {
  char result = r.process();
  if (result == DIR_CW)
    set_frequency(1);
  else if (result == DIR_CCW)
    set_frequency(-1);
}


/**************************************/
/* Change the frequency               */
/* dir = 1    Increment               */
/* dir = -1   Decrement               */
/**************************************/
void set_frequency(short dir)
{
  switch (act_clk)
  {
    case 0:                 // HF frequency
      if (dir == 1)
        vfo_hf += radix;
      if (dir == -1) {
        if (vfo_hf < radix) break; // to prevent negative value
        vfo_hf -= radix;
      }
      break;
    case 1:                 // HF frequency (only if RIT is on)
      if (dir == 1)
        vfo_hf += radix;
      if (dir == -1) {
        if (vfo_hf < radix) break; // to prevent negative value      
        vfo_hf -= radix;
      }
      break;
    case 2:                 // IF frequency
      if (dir == 1)
        vfo_if += radix;
      if (dir == -1) {
        if (vfo_if < radix) break; // to prevent negative value      
        vfo_if -= radix;
      }
      break;
  }

  if(vfo_hf > F_MAX)
    vfo_hf = F_MAX;
  if(vfo_hf < F_MIN)
    vfo_hf = F_MIN;

  changed_f = true;
}


/**************************************/
/* Read the buttons with debouncing   */
/**************************************/
boolean get_button()
{
  if (!digitalRead(ENCODER_BTN))            // Stepsize
  {
    delay(20);
    startTime = millis();                   // Start counting    
    if (!digitalRead(ENCODER_BTN))
    {
      while (!digitalRead(ENCODER_BTN));
      stepflag = true;      
    }
    duration = millis() - startTime;        // Total time pressed
  }
  else if (!digitalRead(CALIBRBTN))         // Calibrate
  {
    delay(20);
    if (!digitalRead(CALIBRBTN))
    {
      while (!digitalRead(CALIBRBTN));
      calflag = true;
    }
  }
  else if (!digitalRead(TXSWITCH))         // Selection
  {
    delay(20);
    if (!digitalRead(TXSWITCH))
    {
      while (!digitalRead(TXSWITCH));
      modeflag = true;
    }
  }  
  if (stepflag | calflag | modeflag) return 1;
  else return 0;
}


/********************************************************************************
 * RIT switch handling
 * Switch to small stepsize (100 Hz)
 *******************************************************************************/
void rit_switch()                               // Read RIT_SWITCH
{
  if (!digitalRead(RITSWITCH) && !ritset){     // RIT on
    act_clk = 1;
    ritset = true;
    vfo_s = vfo_hf;                             // Save Tx freq
    old_radix = radix;                          // Save actual stepsize
    radix = 100;                                // Set stepsize to 100 Hz
  }
  else if (digitalRead(RITSWITCH) && ritset){  // RIT 0ff
    act_clk = 0;                                // RTx mode
    ritset = false;
    vfo_hf = vfo_s;                             // Restore to original vco_t
    radix = old_radix;                          // Back to old stepsize
    disp_txt = 0;                               // Clear line
    
// Update LO frequency based on the restored HF frequency    
    #if defined(UPPER)
      vfo_lo = vfo_hf + vfo_if;                   // Upper / lower mixing
    #elif defined(LOWER) 
      vfo_lo = vfo_hf - vfo_if;    
    #endif
    si5351.set_freq((vfo_lo * SI5351_FREQ_MULT), SI5351_PLL_FIXED, SI5351_CLK1);
  }
}

/**************************************/
/* Displays the frequency and stepsize*/
/**************************************/
void display_frequency()
{
  char LCDstr[10];
  char Hertz[7];
  int p,q = 0;
  uint32_t freq = 0ULL;
  display.clearDisplay();

  switch(act_clk)
  {
    case 0:                               // HF frequency
      freq = vfo_hf;
      break;
    case 1:                               // HF frequency (Used in RIT Mode)
      freq = vfo_hf;
      break;
    case 2:                               // IF frequency
      freq = vfo_if;
      break;
  }

  display.setCursor(100,16);
  display.setTextSize(1);  
  
  Hertz[1]='\0';                          // empty array
  sprintf(LCDstr, "%ld", freq);           // convert freq to string
  p=strlen(LCDstr);                       // determine length
  
  if (p>6){                               // MHz
    display.print(F("MHz"));
    q=p-6;
    strcpy(Hertz,LCDstr);                 // get Herz digits (6)
    strcpy(LCDstr+q,Hertz+(q-1));         // copy into LCDstr and add to MHz
    LCDstr[q]='.';                        // decimal point
  }
  else {                                  // KHz
    display.print(F("KHz"));
    q=p-3;
    strcpy(Hertz,LCDstr);                 // get Herz digits (3)
    strcpy(LCDstr+q,Hertz+(q-1));         // copy into LCDstr and add to KHz
    LCDstr[q]='.';                        // decimal point
  }

  switch (p)                              // display stepsize
  {
    case 4:                               //  1 KHZ
      display.setCursor(48,0);
      break;
    case 5:                               //  10 KHZ
      display.setCursor(36,0);
      break;
    case 6:                               // 100 KHZ
      display.setCursor(24,0);
      break;
    case 7:                               //   1 MHZ
      display.setCursor(12,0);
      break;
    case 8:                               //  10 MHZ
      display.setCursor(0,0);
      break;
    case 9:                               // 100 MHZ
      display.setCursor(0,0);
      break;
  }
    
  display.setTextSize(2);  
  display.println(LCDstr);
  display_settings();
}


/**************************************/
/* Displays step, mode and version    */
/**************************************/
void display_settings()
{
// Stepsize  
  display.setCursor(8, 40);  
  display.setTextSize(1);  
  display.print(F("Step:"));
  
  switch (radix)
  {
    case 1:
      display.println(F("   1Hz"));
      break;
    case 10:
      display.println(F("  10Hz"));
      break;
    case 100:
      display.println(F(" 100Hz"));
      break;
    case 1000:
      display.println(F("  1kHz"));
      break;
    case 10000:
      display.println(F(" 10kHz"));
      break;
    case 100000:
      display.println(F("100kHz"));
      break;
    case 1000000:
      display.println(F("  1MHz"));
      break;
  }

// Mode
  display.setCursor(100, 40);  
  switch (act_clk)
  {
    case 0:
      display.println(F("TRx"));
      break;
    case 1:
      display.println(F("RIT"));
      break;
    case 2:
      display.println(F("IF "));
      break;
  }

// Version  
  display.setCursor(15, 55);  
  display.print(F("Si5351 vfo V.4.0"));

// Messages
  display.setCursor(12, 25);
  switch (disp_txt)
  {
    case 0:
      display.print(F("                 "));   // clear line    
      break;
    case 1:
      display.print(F("** Turn RIT Off *"));
      break;
    case 2:
      display.print(F("*** Set to TRx **"));
      break;
    case 3:
      display.print(F("** Calibration **"));
      break;      
    case 4:
      display.print(F("* Calibration OK!"));
      break;      
  }
  display.display();
}


/**************************************/
/*            S E T U P               */
/**************************************/
void setup()
{
  Serial.begin(115200);
  Wire.begin();
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)

// Read EEPROM
  radix = eeprom_read_dword((const uint32_t *)EE_SAVED_RADIX);
  if ((radix < 10ULL) | (radix > 1000000ULL)) radix = 100ULL;  
  
  vfo_hf = eeprom_read_dword((const uint32_t *)EE_SAVED_AFREQ);
  if ((vfo_hf < F_MIN) | (vfo_hf > F_MAX)) vfo_hf = 14000000ULL;
  
  test = (vfo_hf / 10);                       // Round to 10Hz
  vfo_hf = test * 10;

  vfo_if = eeprom_read_dword((const uint32_t *)EE_SAVED_BFREQ);
  if ((vfo_if < F_MIN) | (vfo_if > F_MAX)) vfo_if = 9000000ULL;  

  test = (vfo_if / 10);                       // Round to 10Hz
  vfo_if = test * 10;

  vco_c = 0;
  if (eeprom_read_dword((const uint32_t *)EE_SAVED_CALBR) == 0x60)  {
    vco_c = eeprom_read_dword((const uint32_t *)EE_SAVED_OFSET);
  }  
  xt_freq = SI5351_XTAL_FREQ + vco_c;

//initialize the Si5351
  si5351.set_correction(0); // Set to zero because I'm using an other calibration method
  si5351.init(SI5351_CRYSTAL_LOAD_8PF, xt_freq);    // Frequency get from settings in VFO_si5351.h file
  si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
  
// Set CLK0 to output the starting "HF" frequency as set above by vfo = ?
  si5351.set_freq((vfo_hf * SI5351_FREQ_MULT), SI5351_PLL_FIXED, SI5351_CLK0);
  si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_2MA);
// Set CLK1 to output the LO frequncy = HF +/- IF frequency
  #if defined(UPPER)
    vfo_lo = vfo_hf + vfo_if;                   // Upper / lower mixing
  #elif defined(LOWER) 
    vfo_lo = vfo_hf - vfo_if;    
  #endif
  si5351.set_freq((vfo_lo * SI5351_FREQ_MULT), SI5351_PLL_FIXED, SI5351_CLK1);
  si5351.drive_strength(SI5351_CLK1,SI5351_DRIVE_2MA);
// Set CLK2 to output bfo frequency
  si5351.set_freq((vfo_if * SI5351_FREQ_MULT), SI5351_PLL_FIXED, SI5351_CLK2);
  si5351.drive_strength(SI5351_CLK2,SI5351_DRIVE_2MA);
  
// Encoder setup
  pinMode(ENCODER_BTN, INPUT_PULLUP);
  PCICR |= (1 << PCIE2);                       // Enable pin change interrupt for the encoder
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);

  sei();                              // Start interrupts

// Pin Setup
  pinMode(CALIBRBTN, INPUT_PULLUP);   // Calibrate
  pinMode(RITSWITCH, INPUT_PULLUP);   // RIT Switch
  pinMode(TXSWITCH,  INPUT_PULLUP);   // Select TRx or BFO

//  Timer
  startMillis = millis();             // Reset actual freq store timer
  actupdt = true;    
  
// Display first time  
  display.clearDisplay();
  display.setTextColor(WHITE);
  display_frequency();                // Update the display
}

/**************************************/
/*             L O O P                */
/**************************************/
void loop()
{
  if (disp_txt == 4) {
    delay(3000);                  // Display calibration OK and wait 3 seconds
    disp_txt = 0;                 // Clear text line
  }

  Serial.println(actupdt);
  
// Update the display if the frequency has been changed
  if (changed_f)  {
    display_frequency();

    if (act_clk == 0 && !kalibrate)                   // No Tx update during calibrate
      si5351.set_freq((vfo_hf * SI5351_FREQ_MULT), SI5351_PLL_FIXED, SI5351_CLK0);
    else if (act_clk == 2)                            // BFO update
      si5351.set_freq((vfo_if * SI5351_FREQ_MULT), SI5351_PLL_FIXED, SI5351_CLK2);      
// Update LO frequency    
    #if defined(UPPER)
      vfo_lo = vfo_hf + vfo_if;                   // Upper / lower mixing
    #elif defined(LOWER) 
      vfo_lo = vfo_hf - vfo_if;    
    #endif
    si5351.set_freq((vfo_lo * SI5351_FREQ_MULT), SI5351_PLL_FIXED, SI5351_CLK1);

    changed_f = false;
    disp_txt = 0;                   // Clear line
    startMillis = millis();         // Reset actual freq store timer
    actupdt = false;  
  }

  rit_switch();                     // read RIT switch

// Store actual freq and other settings once per 5 seceonds after frequency change
  if((millis() - startMillis) > 5000 && !actupdt) {
    eeprom_write_dword((uint32_t *)EE_SAVED_AFREQ, vfo_hf);
    eeprom_write_dword((uint32_t *)EE_SAVED_BFREQ, vfo_if);
    startMillis = millis();                   // Reset actual freq store timer   
    actupdt = true;
    Serial.println("Act freq and BFO stored"); 
  }
  
// Button press
// Also stored the last used frequency together with the step size before store
//
  if (get_button()) { 
    if (stepflag) {                 // Stepsize button
      if (duration > 500)  {        // For a long time then prev step
        switch (radix)
        {
        case 1000000:
          radix = 100000;
          break;
        case 100000:
          radix = 10000;
          break;
        case 10000:
          radix = 1000;
          break;
        case 1000:
          radix = 100;
          break;
        case 100:
          radix = 10;
          break;
        case 10:
          radix = 1;
          break;
        case 1:
          radix = 1000000;
          break;               
        }
      }  
      else {
        switch (radix)
        {
        case 1:
          radix = 10;
          break;
        case 10:
          radix = 100;
          break;
        case 100:
          radix = 1000;
          break;
        case 1000:
          radix = 10000;
          break;
        case 10000:
          radix = 100000;
          break;
        case 100000:
          radix = 1000000;
          break;
        case 1000000:
          radix = 1;
          break;       
        }
      }     
      eeprom_write_dword((uint32_t *)EE_SAVED_RADIX, radix);  // Store stepsize
      stepflag  = false;
    }
    else if (modeflag)  {         // Mode button
      if (act_clk == 0) act_clk = 2; else act_clk = 0;
//      eeprom_write_dword((uint32_t *)EE_SAVED_BFREQ, vfo_if);
      modeflag = false;  
      disp_txt = 0;                                 // Clear line
    }
    else if (calflag) {                             // Calibrate button
      if (!digitalRead(RITSWITCH)){                // RIT is on
        disp_txt = 1;                               // Message set RIT off
      }
      else if (act_clk == 2){                       // BFO mode on
        disp_txt = 2;                               // Message set BFO off        
      }
      else if (!kalibrate)  {                       // Start calibrate
        vfo_s = vfo_hf;                             // Save actual freq
        old_radix = radix;                          // and stepsize
        vfo_hf = SI5351_XTAL_FREQ;                  // en set to default x-tal
        disp_txt = 3;                               // Message Calibrate
        kalibrate = true;
        radix = 10;                                 // Set to 10 Hz        
        si5351.set_freq((vfo_hf * SI5351_FREQ_MULT), SI5351_PLL_FIXED, SI5351_CLK0); // Set HF Freq
      }
      else if (kalibrate) {                         // after tuning x-tal freq
        kalibrate = false;
        vco_c = vfo_hf - SI5351_XTAL_FREQ;          // difference
        vfo_hf = vfo_s;                             // restore freq
        radix = old_radix;                          // and stepsize
        disp_txt = 4;                               // Message Calibrate OK
        
        eeprom_write_dword((uint32_t *)EE_SAVED_OFSET, vco_c);        // store correction
        xt_freq = SI5351_XTAL_FREQ + vco_c;                           // Calibrated x-tal freq
        eeprom_write_dword((uint32_t *)EE_SAVED_CALBR, 0x60);         // Calibrated
        si5351.init(SI5351_CRYSTAL_LOAD_8PF, xt_freq);                // Initialize
        si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);        
        si5351.set_freq(vfo_if * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK2);   // correct BFO frequency
        si5351.set_freq(vfo_hf * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);   // Correct HF freq
        #if defined(UPPER)
          vfo_lo = vfo_hf + vfo_if;                 // Upper / lower mixing
        #elif defined(LOWER) 
          vfo_lo = vfo_hf - vfo_if;    
        #endif
        si5351.set_freq(vfo_lo * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK1);   // correct LO frequency
      }
      calflag = false;
    }
  } // end get_button
  
  display_frequency();                              // Update display
} // end while loop

THX. Perhaps it would speed things up if you could direct us to a particular strange Boolean area of your code.

a7

Also given the complexity, you must have a previous working code that you tested. please post that.

approx line 476. Every void loop() starts with this (if in kalibrate/calibrate mode 4):

    delay(3000);                  // Display calibration OK and wait 3 seconds

which may cause "unresponsiveness"

Is a line below a place where you have experienced the "boolean issue" ?

1 Like

| is being used instead of || in may places but that still should do the right thing as it's always done with truth values that will get promoted to 0 or 1, so a bitwise OR will lead to the same outcome

I suspect you are writing into memory you don't own. Make Hertz[] larger.

  Hertz[1]='\0';                          // empty array
  sprintf(LCDstr, "%ld", freq);           // convert freq to string
  p=strlen(LCDstr);                       // determine length
  
  if (p>6){                               // MHz
    display.print(F("MHz"));
    q=p-6;
    strcpy(Hertz,LCDstr);                 // get Herz digits (6)
2 Likes

to be honest I didn't catch using the | instead of || and drew attention to the line for another reason :slight_smile:

OK

this would probably be better written as

return stepflag || calflag || modeflag;

in you display_frequency() function, you declare Hertz to be 7 chars. You then try to stuff something larger than 6 into it.

  sprintf(LCDstr, "%ld", freq);           // convert freq to string
  p = strlen(LCDstr);                     // determine length

  if (p > 6) {                            // MHz
    display.print(F("MHz"));
    q = p - 6;
    strcpy(Hertz, LCDstr);                // get Herz digits (6)
    strcpy(LCDstr + q, Hertz + (q - 1));  // copy into LCDstr and add to MHz
    LCDstr[q] = '.';                      // decimal point
  }

Image your frequency is 10 MHz (10,000,000) so

LCDStr would be "10000000"
p = 8

and then you try to stuff all 8 of those chars into Hertz.

Also, your ISR call set_frequency() so all those global variables used in that function should be declared volatile

1 Like

Hello all,

Many thanks for all the comments!
I'm going to check them all and I'm hoping for a solution.
B.T.W. in the loop section this statement Serial.println(actupdt); is added after which everything worked again...
I'm going to work!

Thanks again!
Rob

Which is a good reason to enter the 21st century and use "or" instead of "||". I got a message block saying my reply was too similar to what was quoted, so I will try saying la laa laaa... not impressed..

1 Like

I think it dates back from 1995 so it’s last millenium stuff too :wink:

It's such an obvious trap, just like "=" and "==".