Help with Boolean, interpreting Data and displaying 'Yes/No'

Sorry for the uneducated topic, learning as I am going and this seems to be something that I can't google/search this forum for guidance

I am developing a board and code to read the CAN data from my aftermarket ECU (Haltech) and display it on a 2.04 OLED

I have base code that reads the CAN address, have code in place to convert the datastream into usable data to display, and I am currently working on a butchered piece of code that I am using to Demo/update for templating reasons.

I have ECU values set which I edit to display in my template to make sure my display.setCursor is all where I want it, the only issue I have is trying to fake display the boolean data from a particular stream and have it display as YES or NO

With my other data, simply having if (VALUE1 > 100) ... display at setcursor A, if (VALUE1 < 100) ... display at setcursor B.

I don't understand how to initially define/reference Boolean states up where my ECU values are (if I even need to) and have it work the same way as the raw data does

My basic thinking was trying to use either 'if (VALUE5 = 0) ... display.print ("NO")' or 'if (VALUE5 = false) ... display.print("NO")' to make it follow the same algorithm that I use for the raw data but it doesn't seem to work.

I have another code that I use in the realworld that interprets the CAN which works, I just have the code below that I use for ironing out templates for my various pages

The data that the Decel Cut and Transient uses are defined in the CAN protocol that I am using as 0=Off, 1=On

Will attach the code in this post as an aid

#include <Adafruit_GFX.h>                                               //OLED GFX Library
#include <Adafruit_SSD1306.h>                                           //OLED Library (for 1.3 inch, should work on 2.4inch)
#include <mcp_can.h>                                                    //CAN Library
#include <SPI.h>                                                        //Hardware SPI Library
#include <EEPROM.h>                                                     //EEPROM Library

const byte led = 13;                                                    //Onboard LED used as CAN comms indicator                                                  
//const int SPI_CS_PIN = 17;                                              //Define SPI CS for CAN
 
//OLED Pins Hardware SPI
//#define OLED_VCC         5V       RED
//#define OLED_GND         GND      BLACK
//#define OLED_MOSI        MOSI     BLUE
//#define OLED_CLK         SCK      YELLOW
#define OLED_DC            5        //GREEN
#define OLED_CS            6        //ORANGE
#define OLED_RESET         4        //WHITE
Adafruit_SSD1306 display(/*OLED_MOSI, OLED_CLK, */OLED_DC, OLED_RESET, OLED_CS);

#define SCREEN_WIDTH 128                                                // OLED display width, in pixels
#define SCREEN_HEIGHT 64                                                // OLED display height, in pixels

//SCREEN INFO
//128 x 64
//DIN - MOSI
//CLK - SCLK
//VCC - 5v
//GND - Ground
//CS - Chip Selection
//DS - Data/Command

//BUTTON CONFIG
const byte button = 12;                                                  // Button input is D12 (this receives ground which D8 supplies)
long buttonTimer = 0;
long longPressTime = 750;
boolean buttonActive = false;
boolean longPressActive = false;

//EEPROM CONFIG
byte addr = 1;                                                          // Initialise the EEPROM address
byte buttonPushCounter = EEPROM.read(1);                                // Counter for the number of button presses (get value from EEPROM)

//CAN BUS Configuration
unsigned char rxLen = 0;                                                //Message rx Length
unsigned char rxBuf[8];                                                 //Number of bytes (0,1,2...6,7)
MCP_CAN CAN0(17);                                               //Set CAN CS pin (as stated in manual)
byte CANfilterset = 0;                                                  //Check if filter is set

//ECU VALUES
int VALUE1 = 1200;                                                         // VALUE1 integer
int VALUE2 = 110;                                                         // VALUE2 integer
int VALUE3 = 0;                                                         // VALUE3 integer
int VALUE4 = 0;                                                         // VALUE4 integer
int VALUE5 = 0;
//boolean true = YES;
//boolean false = NO;
float FVALUE1 = 0;                                                      // VALUE1 floating point (decimal place numbers)
float FVALUE2 = 0;                                                      // VALUE2 floating point (decimal place numbers)
float FVALUE3 = 0;                                                      // VALUE3 floating point (decimal place numbers)
float FVALUE4 = 0;                                                      // VALUE4 floating point (decimal place numbers)

//SCREEN 1 HEADING, DATA AND MAX/MIN VALUES
int MAX1 = -10000;
int MAX2 = -10000;
int MAX3 = -10000;
int MAX4 = -10000;

int MIN1 = 10000;
int MIN2 = 10000;
int MIN3 = 10000;
int MIN4 = 10000;

float FMAX1 = -10000;
float FMAX2 = -10000;
float FMAX3 = -10000;
float FMAX4 = -10000;

float FMIN1 = 10000;
float FMIN2 = 10000;
float FMIN3 = 10000;
float FMIN4 = 10000;

int ScreenOff = 0;

void setup() {
  Serial.begin(115200);                                                 // Serial Comms speed

  pinMode(led, 13);                                                     // Setup Pin D13 as Output Led

  if (buttonPushCounter >= 6)                                           // On first run EEPROM could be any value 0-254
  { EEPROM.write(1, 0);                                                 // If it is above 3, set it to zero to agree with the 'if' loop
  }

  display.begin(SSD1306_SWITCHCAPVCC);                                  // Initialise Screen
  display.setTextWrap(false);

  pinMode(button, INPUT_PULLUP);                                        //Button config, D8 supplies ground to D12 
  pinMode(8, OUTPUT);
  digitalWrite(8, LOW);

  display.setRotation(0);                                               // Set rotation (0) Normal, (2) 180 deg

  display.clearDisplay();
  display.setTextSize(1);                                               // Splash screen
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("JZX100 TEST CODE");

  display.display();
  delay(500);
 
  display.clearDisplay();
}
void loop(){
////-------------------------------------------------------------------------------------------
          display.setTextSize(1);
          display.setCursor(23, 0);
          display.print("RPM");

          if (VALUE1 < 1000) {
            display.setTextSize(2);
            display.setCursor(13, 12);
            display.print(VALUE1, 1);
          }

          if (VALUE1 > 1000) {
            display.setTextSize(2);
            display.setCursor(8, 12);
            display.print(VALUE1, 1);
          }

          
          display.setTextSize(1);
          display.setCursor(81, 0);
          display.print("SPEED");

          if (VALUE2 < 100) {
            display.setTextSize(2);
            display.setCursor(85, 12);
            display.print(VALUE2, 1);
          }
          if (VALUE2 > 100) {
            display.setTextSize(2);
            display.setCursor(79, 12);
            display.print (VALUE2, 1);
          }
          

          display.setTextSize(1);
          display.setCursor(5, 32);
          display.print("DECEL CUT");

          if (VALUE5 = 0) {
            display.setTextSize(2);
            display.setCursor(15, 44);
            display.print(false, 1);
          }
          if (VALUE5 = 1) {
            display.setTextSize(2);
            display.setCursor(15, 40);
            display.print(true, 1);
          }

          
          display.setTextSize(1);
          display.setCursor(69, 32);
          display.print("TRANSIENT");
          
          if (VALUE5 = 0) {
            display.setTextSize(2);
            display.setCursor(15, 79);
            display.print(false, 1);
          }
          if (VALUE5 = 1) {
            display.setTextSize(2);
            display.setCursor(15, 75);
            display.print(true, 1);
          }
          
          display.display();
          delay(50);

}

The basic states of a boolean id TRUE or FALSE. What values those 2 conditions have depends on the compiler. As You say, 0 or 1, none zero are common definitions.

What is the question "now"? Maybe late here....

A Boolean value is either zero (false) or non-zero (true)

CODE

value = TRUE:  // e.g. non zero value
print( value ? ”NO” : “YES”;

The basic syntax of using the ternary operator is thus:
(condition) ? (if_true) : (if_false)

Which is basically the same as:

if (condition)
    if_true;
else
    if_false;

I guess my question is just in relation to how to input the code for boolean values and use the same format that I've used for the other data to get it to display

Picture attached is the screen running the code I posted in the OP, is this something where I can't 'spoof' the boolean input like I have been doing for the other data values? Does it need the actual CAN feed outputting the boolean data for it to register?

EDIT: the current YES under Decel cut is there due to code error surrounding this boolean issue

Booleans should have the values "true" or "false", nothing else.

Is it as easy as

if (VALUE5 = false) {
            display.setTextSize(2);
            display.setCursor(15, 79);
            display.print("NO");
}
if (VALUE5 = true) {
            display.setTextSize(2);
            display.setCursor(15, 79);
            display.print("YES");
}

That's backwards: should be ? "YES" : "NO"

Comparison uses double-equal ==. Single-equal is assignment, with the result the same as the value being assigned. So that's always false.

Better yet, when checking a boolean, just use the variable name, or the boolean-NOT operator: !

boolean initialized;

//...
if (!initialized) {  // pronounced "if not initialized"

// much later...
if (initialized) {

And no point checking for both boolean values serially; that's what else is for.

if (initialized) {
  // ...
} else {
  // not initialized
}

Aside from the =, that's a bad example because the only difference between the two blocks is NO vs YES. IOW, that could be just

display.setTextSize(2);
display.setCursor(15, 79);
display.print(VALUE5 ? "YES" : "NO");

If you assign a number -- any number -- to a boolean, if it is zero that makes it false, and otherwise it is true

boolean overflow;
overflow = 0.0;
Serial.print(overflow ? "YES" : "NO");
overflow = 42;
Serial.print(overflow ? "YES" : "NO");

More likely though, you will assign it the result of a boolean expression, based on some other value

overflow = micros() > 5;
Serial.println(overflow ? "YES" : "NO");
overflow = micros() > 400;
Serial.println(overflow ? "YES" : "NO");
Serial.println(micros());

If there is no "live" expression, you would initialize it to either false or true, whichever makes more sense. If you don't initialize it explicitly, it will be initialized according the usual C++ rules for variables: global and static will be false, and otherwise, "it depends".

1 Like

Thanks… my ipad was not letting me select blocks of text for tagging !
I missed that.

I understand what you have said in your post so far

The reason those two blocks are similar apart from the YES/NO is that I am trying to set a template up so the word that is displayed onto the screen is centralised to the header that it above it (see photo)

How would I go about writing code that displays false/NO and not false/YES in a way that allows me to adjust the display.setCursor point for either output independently?

If there is no "live" expression, you would initialize it to either false or true , whichever makes more sense. If you don't initialize it explicitly, it will be initialized according the usual C++ rules for variables: global and static will be false , and otherwise, "it depends".

I had a look at how to initialise via the Arduino Documentation, will inputting this into the base of my code affect how the button operates? There are a few things in my base code that I have sampled from another code and that is the only mention of bool/boolean I had seen until encountering this issue with boolean data streams

We can easily open a can of worms trying to position text. For example, you could have a library that knows the font in use, and given the size, how wide a given piece of text is. You could then in theory do something like

textGizmo.setAlignment(CENTER);
textGizmo.printAt(3, 40, "Whatever");

and it could center it for you. But if that's not the case, and it's mostly done by hand, then it's more like

display.setTextSize(2);
if (decelCut) {
  display.setCursor(15, 79);
  display.print("YES");
} else {
  display.setCursor(20, 79);
  display.print("NO");
}

If the first argument to setCursor is the X position, then you need to be further to the right if the word is shorter. You can then tweak the positions until they both look centered.

As for initializing the variable, it has no automatic effect unless the extra byte causes you to run out of memory (unlikely). Otherwise, it only has as much effect as you let it. You don't necessarily need to initialize its value, if the value is always set before you use it.

int rpm;
int speed;
bool decelCut;  // use the official `bool` instead of the alias `boolean`

void loop() {
  rpm = readTheRPM();
  speed = calculateTheSpeedUsingRPM();
  decelCut = iHaveNoIdeaHowYouDefineItButTheresGottaBeSomeLogicHere();
  updateTheDisplay();
}

I marked this as the solution, my code compiled in IDE which I am marking as a success (yay)

This is how I ended up going about it in the setup:

...
bool decelCutActive = false;
bool transientThrottleActive = false;
...

and in the body:

          display.setTextSize(1);
          display.setCursor(5, 32);
          display.print("DECEL CUT");

          if (decelCutActive) {
            display.setTextSize(2);
            display.setCursor(22, 44);
            display.print("NO");
          }else{
            display.setTextSize(2);
            display.setCursor(15, 44);
            display.print("YES");
          }

I would plug it into my car and verify the states working (needs CAN initiated to allow the code to move along) in relation to their Print in word but the battery has died and it is far too late in the day to be jump starting it and having it idle (sigh)

I will report back tomorrow how it all goes. At this stage the states on the page both read "YES" but I assume that is because there is technically no data input for the code (as there is no CAN connection with my dummy code for templating) to know the state is "false" so it is continuing on the "}else{" route.

Thank you for everyones input!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.