1

I'm getting my first steps on Arduino and I'm trying to do an exercise where I have to draw a graph bar in a 16x2 LCD that indicates the values read from a vector of 16 integer elements amplified by the value read from a potentiometer (connected to the analog pin A0) during runtime. The graph should change in real-time as I move the cursor of the potentiometer to the left or right.

I have the following code structure:

void loop() {

// Read the 16 vector elements and map then to the screen height ...

// Print out their values multiplied by the value read form the potentiometer, to the serial monitor ...

// Draw a bar for each one of the vector elements (you will have 16 bars in the end)...

// If the graph has reached the screen edge do not amplify it anyfurther. If it has reached the bottom, do the same

//Wait a bit. Start drawing everything from scratch.

So far what I have is:

#include<LiquidCrystal.h>

// Create an LCD object and connect control wires

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int vector[16] = {3, 7, 10, 15, 28, 12, 43, 1, 6, 19, 29, 23, 54, 76, 57, 66};

int value=0;

void setup(){
  Serial.begin(9600);
  
  // Specify the LCD's number of columns and rows
  
  lcd.begin(16, 2);
}

void loop(){
  
  value = analogRead(A0);

  for(int i=0; i<16; i++){
    int vector2[i] = map(vector[i], 0, 1024, 0, 20);
    Serial.println(vector2[i]*value);
  }
}

However I'm getting the following error so far:

 In function 'void loop()':
28:25: error: array must be initialized with a brace-enclosed initializer
 exit status 1

Also I can't think of a way to do the last 3 steps of the code structure I have. I know that if i would want to print a bar like a character I could do:

#include<LiquidCrystal.h>

// Create an LCD object and connect control wires

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
byte bar[] ={B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111};

void setup(){
  Serial.begin(9600);
  
  // Specify the LCD's number of columns and rows
  
  lcd.begin(16, 2);
  lcd.createChar(0, bar);
}

void loop(){
lcd.setCursor(0,0);
cd.write(byte(0));
  
}

But even this would only print a column in the first row and column and not in both rows and first column of the LCD.

Can someone help me with the error I already have and give me some lights on how to do the last 3 steps of the code structure?

6
  • review how to operate on arrays ... arduino.cc/reference/en/language/variables/data-types/array
    – jsotola
    Commented Nov 2, 2020 at 19:09
  • your code repeatedly prints to location 0,0 ... i do not see what is unclear about that
    – jsotola
    Commented Nov 2, 2020 at 19:10
  • 1
    You're using an array vector2[] inside loop() that has an undefined size because you did not properly declare it. The error is quite descriptive and will also highlight the line where the error was found.
    – StarCat
    Commented Nov 2, 2020 at 19:11
  • 1
    Okay got the part of the vector2 already! Thanks Commented Nov 2, 2020 at 19:17
  • 1
    @Majenko that was what I was thinking about but can't think of a way to put a column character on both rows or how to draw it deppending on the value of the value2*potentiometer Commented Nov 2, 2020 at 19:47

1 Answer 1

1

First off you're going to need to define some custom characters. There's examples for how to do that. You want characters that gradually fill up from the bottom to full, such as:

▁ ▂ ▃ ▄ ▅ ▆ ▇ █

Now, you have 8 lines per character and two lines of characters, which gives you a possible drawing range of 0-16. So you need to map your maximum range into that 0-16 span.

Finally you want to create a function to draw a single bar. This will take two parameters - the position of the bar (x) and the height of the bar (y). A simple little bit of mathematics later and you can work out what to print in the upper and lower characters.

  • If the value is = 0:
    • Both top and bottom are spaces
  • If the value is <= 8:
    • The bottom character is the one with the same number of lines as the value
    • The top character is empty.
  • If the value is > 8:
    • The bottom character is the one with all 8 lines filled
    • The top character is the one with the value - 8 number of lines filled.

So you may end up with something like (note - untested):

const uint8_t bars[8][8] = {
    { 0, 0, 0, 0, 0, 0, 0, 0xff },
    { 0, 0, 0, 0, 0, 0, 0xff, 0xff },
    { 0, 0, 0, 0, 0, 0xff, 0xff, 0xff },
    { 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff },
    { 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff },
    { 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    { 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
};

void setup() {
    // other stuff, like setting up the LCD...

    for (uint8_t i = 0; i < 8; i++) {
        lcd.createChar(i, bars[i]);
    }
}

void drawBar(uint8_t x, uint8_t y) {
    char top, bot;

    if (y == 0) { // Both spaces
        top = ' ';
        bot = ' ';
    } else if (y <= 8) { // Bottom has bar graph, top is empty
        top = ' ';
        bot = val - 1; // Characters start at 0, so 1-8 is 0-7
    } else if (y <= 16) { // Bottom is full, top has bar graph
        top = (y - 9); // Characters start at 0, so 9-16 is 0-7
        bot = 7;
    } else { // Overflow - both top and bottom full
        top = 7;
        bot = 7;
    }

    lcd.setCursor(x, 0);
    lcd.write(top);
    lcd.setCursor(x, 1);
    lcd.write(bot);
}

void loop() {
    // your stuff in here
}

Then to draw a bar you just call drawBar 16 times:

for (uint8_t i = 0; i < 16; i++) {
    uint8_t y = <your calculation on vector2[i] here>
    drawBar(i, y);
}

If you've done it right you should end up with something like:

▁█ ▄ ▆█▇   ▃ ▃▇
██▃█▇███▅▆▇█▆██▃

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.