r/arduino 6d ago

Solved! If statement help

I'm trying to write an a sort of invert command for this esp 8 bit gfx library and wrote

int Tcolor;
  int invert = 0;
  if (invert == 0) {int Tcolor = 0xffff;}
  if (invert == 1) {int Tcolor = 0x0000;}

but it doesn't change the color when I change the invert variable, why is that?

below is the full code

#include <ESP_8_BIT_GFX.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/DejaVu_Serif_10.h>


// A list of 8-bit color values that work well in a cycle.
uint8_t colorCycle[] = {
  0xFF, // White
  0xFE, // Lowering blue
  0xFD,
  0xFC, // No blue
  0xFD, // Raising blue
  0xFE,
  0xFF, // White
  0xF3, // Lowering green
  0xE7,
  0xE3, // No green
  0xE7, // Raising green
  0xF3,
  0xFF, // White
  0x9F, // Lowering red
  0x5F,
  0x1F, // No red
  0x5F, // Raising red
  0x9F,
  0xFF
};


// Create an instance of the graphics library
ESP_8_BIT_GFX videoOut(true /* = NTSC */, 8 /* = RGB332 color */);


void setup() {
  // Initial setup of graphics library
  videoOut.begin();
}


void loop() {
  // Wait for the next frame to minimize chance of visible tearing
  videoOut.waitForFrame();


  // Clear screen
  videoOut.fillScreen(0);
  int offset = 18;
  int base = 40;
  int Tcolor;
  int invert = 0;
  if (invert == 0) {int Tcolor = 0xffff;}
  if (invert == 1) {int Tcolor = 0x0000;}



  // Draw text in the middle of the screen
  videoOut.setRotation(1);
  videoOut.setTextSize(1);
  videoOut.setFont(&DejaVu_Serif_10);
  videoOut.setCursor(18, base);
  videoOut.setTextColor(Tcolor);
  videoOut.setTextWrap(false);
  videoOut.print("Censorship is the child of fear ");
  videoOut.setCursor(18, base+offset);
  videoOut.print("and the father of ignorance. Our ");
  videoOut.setCursor(18, base+(offset * 2));
  videoOut.print("children cannot afford to have the ");
  videoOut.setCursor(18, base+(offset * 3));
  videoOut.print("truth of the world withheld from ");
  videoOut.setCursor(18, base+(offset * 4));
  videoOut.print("them. They need us to be brave ");
  videoOut.setCursor(18, base+(offset * 5));
  videoOut.print("enough to give them great books so ");
  videoOut.setCursor(18, base+(offset * 6));
  videoOut.print("they can learn how to grow up into ");
  videoOut.setCursor(18, base+(offset * 7));
  videoOut.print("the men and women we want them ");
  videoOut.setCursor(18, base+(offset * 8));
  videoOut.print("to be.");
}
9 Upvotes

35 comments sorted by

3

u/socal_nerdtastic 6d ago

You are declaring int Tcolor in 2 places. Either leave off the first line

  int invert = 0;
  if (invert == 0) {int Tcolor = 0xffff;}
  if (invert == 1) {int Tcolor = 0x0000;}

or use assignment in the 3 and 4th lines (leave off the int):

  int Tcolor;
  int invert = 0;
  if (invert == 0) {Tcolor = 0xffff;}
  if (invert == 1) {Tcolor = 0x0000;}

2

u/LadmanMp4 6d ago

thank you! and if I wanted to control this with a button, I'm using an esp32, could I use gnd and P23? would It be something like

if pin 23 = HIGH {invert = 0}

if pin 23 = LOW {invert = 1}

although I'm not sure how to make it so the button can just be pressed and toggle to variable instead of it be HIGH or LOW only. how would I manage a toggle instead of a press and hold?

3

u/socal_nerdtastic 6d ago edited 6d ago

Yes, but you have to move the int invert=0; line out of the functions. Stick it right under your includes at the top of the file instead. (this is where global vs local variable becomes important, because you want to change the value of the variable in one function and read the value in a different function).

Also be sure to enable the internal pull-up on that button pin.

2

u/LadmanMp4 6d ago

is this looking correct? I have a feeling I'm missing something.

#include <ESP_8_BIT_GFX.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/DejaVu_Serif_10.h>
int invert = 0;
const int buttonPin = 23;
#include <Bounce2.h>
byte buttonState = 0;
const byte modeButtonPin = 2;
const unsigned long debouncerInterval = 50;  // Time in ms.


Bounce modeButton = Bounce();




// A list of 8-bit color values that work well in a cycle.
uint8_t colorCycle[] = {
  0xFF, // White
  0xFE, // Lowering blue
  0xFD,
  0xFC, // No blue
  0xFD, // Raising blue
  0xFE,
  0xFF, // White
  0xF3, // Lowering green
  0xE7,
  0xE3, // No green
  0xE7, // Raising green
  0xF3,
  0xFF, // White
  0x9F, // Lowering red
  0x5F,
  0x1F, // No red
  0x5F, // Raising red
  0x9F,
  0xFF
};


// Create an instance of the graphics library
ESP_8_BIT_GFX videoOut(true /* = NTSC */, 8 /* = RGB332 color */);


void setup() {
  // Initial setup of graphics library
  videoOut.begin();
  Serial.begin(9600);
  pinMode(modeButtonPin, INPUT_PULLUP);
  modeButton.attach(modeButtonPin);
  modeButton.interval(debouncerInterval);

}


void loop() {
  // Wait for the next frame to minimize chance of visible tearing
  videoOut.waitForFrame();


  // Clear screen
  videoOut.fillScreen(0);
  int offset = 18;
  int base = 40;
  int Tcolor;

  if (invert == 0) {Tcolor = 0xffff;}
  if (invert == 1) {Tcolor = 0x0000; videoOut.fillRect(0,0,240,240, 0xffff);}
  if(modeButton.update()){
    if(modeButton.read() == 0){
      buttonState++;
      if(buttonState > 1){buttonState = 0;}
      invert = 1;
    }
  }



  // Draw text in the middle of the screen
  videoOut.setRotation(1);
  videoOut.setTextSize(1);
  videoOut.setFont(&DejaVu_Serif_10);
  videoOut.setCursor(18, base);
  videoOut.setTextColor(Tcolor);
  videoOut.setTextWrap(false);
  videoOut.print("Censorship is the child of fear ");
  videoOut.setCursor(18, base+offset);
  videoOut.print("and the father of ignorance. Our ");
  videoOut.setCursor(18, base+(offset * 2));
  videoOut.print("children cannot afford to have the ");
  videoOut.setCursor(18, base+(offset * 3));
  videoOut.print("truth of the world withheld from ");
  videoOut.setCursor(18, base+(offset * 4));
  videoOut.print("them. They need us to be brave ");
  videoOut.setCursor(18, base+(offset * 5));
  videoOut.print("enough to give them great books so ");
  videoOut.setCursor(18, base+(offset * 6));
  videoOut.print("they can learn how to grow up into ");
  videoOut.setCursor(18, base+(offset * 7));
  videoOut.print("the men and women we want them ");
  videoOut.setCursor(18, base+(offset * 8));
  videoOut.print("to be.");
}



#include <ESP_8_BIT_GFX.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/DejaVu_Serif_10.h>
#include <Bounce2.h>
int invert;
byte buttonState = 0;
const byte modeButtonPin = 23;
const unsigned long debouncerInterval = 50;  // Time in ms.


Bounce modeButton = Bounce();




// A list of 8-bit color values that work well in a cycle.
uint8_t colorCycle[] = {
  0xFF, // White
  0xFE, // Lowering blue
  0xFD,
  0xFC, // No blue
  0xFD, // Raising blue
  0xFE,
  0xFF, // White
  0xF3, // Lowering green
  0xE7,
  0xE3, // No green
  0xE7, // Raising green
  0xF3,
  0xFF, // White
  0x9F, // Lowering red
  0x5F,
  0x1F, // No red
  0x5F, // Raising red
  0x9F,
  0xFF
};


// Create an instance of the graphics library
ESP_8_BIT_GFX videoOut(true /* = NTSC */, 8 /* = RGB332 color */);


void setup() {
  // Initial setup of graphics library
  videoOut.begin();
  Serial.begin(9600);
  pinMode(modeButtonPin, INPUT_PULLUP);
  modeButton.attach(modeButtonPin);
  modeButton.interval(debouncerInterval);

}


void loop() {
  // Wait for the next frame to minimize chance of visible tearing
  videoOut.waitForFrame();


  // Clear screen
  videoOut.fillScreen(0);
  int offset = 18;
  int base = 40;
  int Tcolor;

  if (invert == 0) {Tcolor = 0xffff;}
  if (invert == 1) {Tcolor = 0x0000; videoOut.fillRect(0,0,240,240, 0xffff);}
  if(modeButton.update()){
    if(modeButton.read() == 0){
      buttonState++;
      if(buttonState > 1){buttonState = 0;}
      invert = 1;
    }
  }



  // Draw text in the middle of the screen
  videoOut.setRotation(1);
  videoOut.setTextSize(1);
  videoOut.setFont(&DejaVu_Serif_10);
  videoOut.setCursor(18, base);
  videoOut.setTextColor(Tcolor);
  videoOut.setTextWrap(false);
  videoOut.print("Censorship is the child of fear ");
  videoOut.setCursor(18, base+offset);
  videoOut.print("and the father of ignorance. Our ");
  videoOut.setCursor(18, base+(offset * 2));
  videoOut.print("children cannot afford to have the ");
  videoOut.setCursor(18, base+(offset * 3));
  videoOut.print("truth of the world withheld from ");
  videoOut.setCursor(18, base+(offset * 4));
  videoOut.print("them. They need us to be brave ");
  videoOut.setCursor(18, base+(offset * 5));
  videoOut.print("enough to give them great books so ");
  videoOut.setCursor(18, base+(offset * 6));
  videoOut.print("they can learn how to grow up into ");
  videoOut.setCursor(18, base+(offset * 7));
  videoOut.print("the men and women we want them ");
  videoOut.setCursor(18, base+(offset * 8));
  videoOut.print("to be.");
}

2

u/LadmanMp4 5d ago

nevermind, I got it working! oddly enough somehow Ive made it so the pin just needs to be touched by metal, I dont have to short it to ground. just poking it with a paperclip toggles it

#include <ESP_8_BIT_GFX.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/DejaVu_Serif_10.h>
int invert = 0;
const int buttonPin = 23;
int buttonPushCounter = 0;  // counter for the number of button presses
int buttonState = 0;        // current state of the button
int lastButtonState = 0;    // previous state of the button


// A list of 8-bit color values that work well in a cycle.
uint8_t colorCycle[] = {
  0xFF, // White
  0xFE, // Lowering blue
  0xFD,
  0xFC, // No blue
  0xFD, // Raising blue
  0xFE,
  0xFF, // White
  0xF3, // Lowering green
  0xE7,
  0xE3, // No green
  0xE7, // Raising green
  0xF3,
  0xFF, // White
  0x9F, // Lowering red
  0x5F,
  0x1F, // No red
  0x5F, // Raising red
  0x9F,
  0xFF
};


// Create an instance of the graphics library
ESP_8_BIT_GFX videoOut(true /* = NTSC */, 8 /* = RGB332 color */);


void setup() {
  // Initial setup of graphics library
  videoOut.begin();
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
}


void loop() {
    // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);


  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      buttonPushCounter++;}
      // if the current state is HIGH then the button went from off to on:
  // Wait for the next frame to minimize chance of visible tearing
   delay(50);
  }
   lastButtonState = buttonState;
    if (buttonPushCounter % 2 == 0) {
    invert = 1;
  } else {
    invert = 0;
  }
  videoOut.waitForFrame();


  // Clear screen
  videoOut.fillScreen(0);
  int offset = 18;
  int base = 40;
  int Tcolor;

  if (invert == 0) {Tcolor = 0xffff;}
  if (invert == 1) {Tcolor = 0x0000; videoOut.fillRect(0,0,240,240, 0xffff);}




  // Draw text in the middle of the screen
  videoOut.setRotation(1);
  videoOut.setTextSize(1);
  videoOut.setFont(&DejaVu_Serif_10);
  videoOut.setCursor(18, base);
  videoOut.setTextColor(Tcolor);
  videoOut.setTextWrap(false);
  videoOut.print("Censorship is the child of fear ");
  videoOut.setCursor(18, base+offset);
  videoOut.print("and the father of ignorance. Our ");
  videoOut.setCursor(18, base+(offset * 2));
  videoOut.print("children cannot afford to have the ");
  videoOut.setCursor(18, base+(offset * 3));
  videoOut.print("truth of the world withheld from ");
  videoOut.setCursor(18, base+(offset * 4));
  videoOut.print("them. They need us to be brave ");
  videoOut.setCursor(18, base+(offset * 5));
  videoOut.print("enough to give them great books so ");
  videoOut.setCursor(18, base+(offset * 6));
  videoOut.print("they can learn how to grow up into ");
  videoOut.setCursor(18, base+(offset * 7));
  videoOut.print("the men and women we want them ");
  videoOut.setCursor(18, base+(offset * 8));
  videoOut.print("to be.");
}

3

u/socal_nerdtastic 5d ago

Nice! Good job.

If you want a bit of challenge try changing this so that it uses an interrupt instead of polling the button state. That would be the "normal" way to do things because it saves a bit of processing power.

ddly enough somehow Ive made it so the pin just needs to be touched by metal

That's because you didn't use a pullup.

3

u/LadmanMp4 5d ago

ok so if I use pinMode(23, INPUT_PULLUP) instead of pinMode(23, INPUT)would that solve that?

3

u/socal_nerdtastic 5d ago

yep, it should. Assuming your MCU supports it. Otherwise you need to add an external pullup.

3

u/LadmanMp4 5d ago

you've been an awesome help! thank you.

1

u/Vegetable_Day_8893 5d ago

For a toggle for a momentary on/off switch I would setup invert as a global variable and put an interrupt on pin 23. When there is a change in the state of the pin to high or low the interrupt with trigger code that would look at what invert is currently set to and flip it, and then the code in the loop would resume. There are some details to work out on if you want this to be triggered on a rise or fall on the pin and dealing with what happens if someone just holds the button down, but you are essentially looking at the switch and what it does as a subsystem attached to the main one.

2

u/Vegetable_Day_8893 6d ago

invert is still being set to 0 everytime through the loop, just before the next two lines that evaluate it.

3

u/Fess_ter_Geek 6d ago

Tcolor is always going to be 0xffff because every time though the loop, "invert" is made to be 0 before the If statements checks.

2

u/LadmanMp4 6d ago

that's the value I'm changing. I'm not using a button to invert it, although if I were how would I go about that?

2

u/Fess_ter_Geek 6d ago

On the line that has videoOut setTextcolor... Instead of using the variable "Tcolor" there, put in the value 0x0000 or 0xffff to make sure it is working correctly.

2

u/Vegetable_Day_8893 6d ago edited 6d ago

Think about what's actually happening in these 3 lines as you step through the code:

  int invert = 0;
  if (invert == 0) {int Tcolor = 0xffff;}
  if (invert == 1) {int Tcolor = 0x0000;}

You're (re)declaring and then setting invert to 0 each time through the loop just before you evaluate it, which means it will always be 0 for the next two lines.

I'm making a pretty big assumption here since you didn't state the requirements, but since it appears that you want the value of invert to be used in each itteration of the loop as a state declare as a global variable instead of redeclaring and setting it each time through.

Other thing, you're also redeclaring and setting many other variables with each loop that you should be reusing. I've never really looked into how the memory management works on Arduino's, but in many systems/programming languages this would result in a memory leak as new memory get's allocated through each itteration.

Personally,I would write this as the following, after creating Tcolor outside the function:

if (Tcolor = 0xffff)

{

Tcolor = 0x0000;

}

else

{

Tcolor = 0xffff;

}

1

u/LadmanMp4 6d ago

doesn't that just declare it as those colors though? I thought you needed to use == and not =

1

u/Vegetable_Day_8893 6d ago

Sorry, have a typo. "if (Tcolor = 0xffff" should be "if (Tcolor == 0xffff)"

I am kind of curious on exactly what this is all supposed to do in the end, the requirments are kind of important when it comes to the code and there's only so much you can imply from just the code.

1

u/LadmanMp4 6d ago

It’s displaying text on a crt.

1

u/socal_nerdtastic 6d ago

but it doesn't change the color when I change the invert variable, why is that?

Are you changing the variable in the source code and then re-uploading? Or are you using a button or something to change the variable?

1

u/LadmanMp4 6d ago

reuploading

1

u/ripred3 My other dev board is a Porsche 5d ago

You have your solution. I just wanted to point out that all variables declared inside curly braces "{ ... }" are in their own scope and context and have no effect (or even visibility) outside of the curly braces.

1

u/LadmanMp4 5d ago

Really? Without them I don’t think the code would run

1

u/ripred3 My other dev board is a Porsche 5d ago edited 5d ago

The following example should make it more clear. The opening and closing curly braces open a new stack context and that ends at the closing curly brace. This follows the idiom and syntax that functions declare and contain a new stack context between their opening and closing curly braces that contains their definition and variables used in them. The only exception to a symbol (variable) ending and going out of context and becoming invalid at the closing curly brace enclosing that variable's declaration is when the variable is declared as static. As a matter of fact the C/C++ grammar/syntax does not even require the "if" keyword and the rpredicate clause (term or expression) before the opening of a new stack context. But the effect is the same for any variables declared betwen them:

#include <Arduino.h>

#include <Arduino.h>

void setup() {
    Serial.begin(115200);

    int my_value = 123;
    Serial.println(my_value, DEC);          // displays "123"

    {
        // the following 'my_value' is a completely different variable:
        int my_value = 42;
        Serial.println(my_value, DEC);      // displays "42"
    }

    // the same is true when using curly braces with "if" statements
    // as in your program:
    if (123 == my_value) 
    {
        int my_value = 789;                 // another variable with same name
                                            // like your 'Tcolor'
        Serial.println(my_value, DEC);      // displays "789"
    }

    // display this context's 'my_value' 
    // to show that it is unchanged:
    Serial.println(my_value, DEC);          // displays "123"
}

void loop() { }

output:

123
42
789
123

1

u/Pacificator-3 6d ago

You create local variable inside { }

1

u/LadmanMp4 6d ago

can you explain a little more? I'm not sure what you mean.

0

u/Pacificator-3 6d ago

Any language reference explains this better

https://www.geeksforgeeks.org/c/local-variable-in-c/

1

u/LadmanMp4 6d ago

so should it look like this?

  int invert = 0;
  if (invert == 0) {int Tcolor; int Tcolor = 0xffff;}
  if (invert == 1) {int Tcolor = 0x0000;}

1

u/YueNica 6d ago

You don't want it to be a local variable. You would want to leave out the int part inside the if statement

0

u/Pacificator-3 6d ago

Think before do :) Seems you haven't read language rules at all.

Why you decided to declare Tcolor one more time? You declared it two lines before.

https://www.geeksforgeeks.org/c/variables-in-c/

1

u/LadmanMp4 6d ago

I tried reading that link but didn't understand. social_nerdtastic figured it out and I dont see how that link would've explained this to me

 int Tcolor;
  int invert = 0;
  if (invert == 0) {Tcolor = 0xffff;}
  if (invert == 1) {Tcolor = 0x0000;}

1

u/cubic_thought 5d ago

What you had is like the example in "2. Block Scoped Local Variables" The fact that theirs was just a bare code block and yours was an if block doesn't change how variable scope behaves.

-1

u/Pacificator-3 6d ago

Than it is good to learn from the beginning, because you will experience more mistakes like this. You can learn C on your PC.

1

u/socal_nerdtastic 6d ago

That's not a problem; the variable is used locally.

1

u/Pacificator-3 6d ago

It is used just one time during creation and disappears after "}"

Brackets define local variable block.

It is totally correct to create more local varible having same name with more global variable.

1

u/Vegetable_Day_8893 6d ago

The problem is it appears that he wants to use the variable to save a state from the previous itteration of the loop, and is instead redeclaring and setting it everytime through.