Unexpected logic? problem with sketch

Hello,

I have a problem with my sketch which runs on an Arduino Nano
using version 1.6.13 of the IDE.

I'm trying to emulate a mechanical moving dial (similar to a bathroom scale) on
a ST7735 screen to show frequency movements. The current frequency is compared to the stored previous frequency
and the display is shifted to the left or right according to the difference in readings.

I have two problems:
First the display moves to the previous frequency and not to the current frequency.
By using on-screen and Serial.print debugging I can see that the current frequency is correct inside of the shift routines.

Second, if the frequencies are the same then the display will not move.
I can see from my code that the criteria for shifting is either >0 or <0 but I cannot think of a way to
force the movement to the last current frequency (as in point one) when there is no shift in values.

I have made a video of the screen and serial monitor output to upload if that would help to better visualise the problems.
I'd be very grateful of any hints / help please.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>

#define cs   10
#define dc   8
#define rst  9

Adafruit_ST7735 display = Adafruit_ST7735(cs,  dc, rst);

int box_y_coord = 25;               // Start of y coordinate for boxes
int box_width = 70;
int box_height = 30;
int box_speed = 2;
int box_offset = 80 - (box_width / 2); // value is currently 45
int shi;
int sli;

bool initialisation_required = true;

int random_frequency;
int current_frequency;
int previous_frequency = 5000;
int shift_in_frequency;

void setup() {

  display.initR(INITR_BLACKTAB);
  display.setRotation(1);           // x begins at left-hand side of the screen, y begins from the top of the screen
  display.setTextColor(ST7735_BLACK);
  display.setTextWrap(0);
  display.setTextSize(2);

  Serial.begin (9600);
  randomSeed(analogRead(0));


  display.fillRect(0,0,160,25,ST7735_YELLOW);  // remove when problem fixed
  display.fillRect(0,55,160,25,ST7735_YELLOW); // remove when problem fixed

  delay(5000); // Give me time to start video

}

void loop() {

  current_frequency = random(4997,5004);
  shift_in_frequency = current_frequency - previous_frequency;
  display.fillRect(0,60,160,80,ST7735_WHITE);
  display.setCursor(2,65);
  display.print("Current:");
  display.print(current_frequency);
  display.setCursor(2,85);
  display.print("Previous:");
  display.print(previous_frequency);
  display.setCursor(2,105);
  display.print("Shift:");
  display.print(shift_in_frequency);
  Serial.print("In main loop - current: ");
  Serial.print(current_frequency);
  Serial.print(" previous: ");
  Serial.print(previous_frequency);
  Serial.print(" shift: ");
  Serial.println(shift_in_frequency);
    
  if (abs(shift_in_frequency) > 5)
     initialisation_required = true;

  if (initialisation_required) {
     setup_initial_display();
     initialisation_required = false;
  }

  if (shift_in_frequency > 0) { // Frequency rising
      shift_higher(shift_in_frequency);
  }
  else if (shift_in_frequency < 0) { // Frequency falling
          shift_lower(0 - (shift_in_frequency));
          }

  previous_frequency = current_frequency;
  shift_in_frequency = 0;
  delay(3000);
  
}

void setup_initial_display() { //Runs once only

  // Draw the left-hand box
  display.drawRect(box_offset - box_width,box_y_coord,box_width,box_height,ST7735_BLACK);
  display.fillRect(box_offset - box_width + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
  // Draw in the frequency
  display.setCursor(box_offset - box_width + 6,box_y_coord + (box_height / 2) - 6);
  display.print(int(current_frequency - 0.01) / 100);
  display.print(".");
  if (int(current_frequency - 0.01)%100 < 10)
     display.print("0");
  display.print(int(current_frequency - 0.01) % 100);

  // Draw the central box
  display.drawRect(box_offset,box_y_coord,box_width,box_height,ST7735_BLACK);
  display.fillRect(box_offset + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
  // Draw in the frequency
  display.setCursor(box_offset + 6,box_y_coord + (box_height / 2) - 6);
  display.print(int(current_frequency) / 100);
  display.print(".");
  if (int(current_frequency)%100 < 10)
     display.print("0");
  display.print(int(current_frequency) % 100);

  // Draw the right-hand box
  display.drawRect(box_offset + box_width,box_y_coord,box_width,box_height,ST7735_BLACK);
  display.fillRect(box_offset + box_width + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
  // Draw in the frequency
  display.setCursor(box_offset + box_width + 6,box_y_coord + (box_height / 2) - 6);
  display.print(int(current_frequency + 0.01) / 100);
  display.print(".");
  if (int(current_frequency + 0.01)%100 < 10)
     display.print("0");
  display.print(int(current_frequency + 0.01) % 100);

  // Draw the gauge line
  display.drawFastVLine(79,25,30,ST7735_RED);
  display.drawFastVLine(80,25,30,ST7735_RED);
  display.drawFastVLine(81,25,30,ST7735_RED);
  display.drawFastVLine(82,25,30,ST7735_RED);

}

void shift_higher(int offset) {
  Serial.print("In shift higher - current: ");
  Serial.print(current_frequency);
  Serial.print(" previous: ");
  Serial.print(previous_frequency);
  Serial.print(" shift: ");
  Serial.println(shift_in_frequency);
  
  shi =  box_width + box_offset; // Is 70 + 45 = 115
  while(shi <= ((offset * box_width) + box_width + box_offset)) { // For example when offset = 1,  limit = 1 * 70 + 70 + 45 = 185

      // Starting box
      display.drawRect(shi - box_width,box_y_coord,box_width,box_height,ST7735_BLACK);
      display.fillRect(shi - box_width + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
      display.setCursor(shi - (box_width) + 6,box_y_coord + (box_height / 2) - 6);
      display.print(int(current_frequency) / 100);
      display.print(".");
      if (int(current_frequency)%100 < 10)
         display.print("0");
      display.print(int(current_frequency) % 100);

      // Previous minus one - SR1
      display.drawRect(shi - (2 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
      display.fillRect(shi - (2 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
      display.setCursor(shi - (2 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
      display.print(int(current_frequency - 1) / 100);
      display.print(".");
      if (int(current_frequency - 1)%100 < 10)
         display.print("0");
      display.print(int(current_frequency - 1)%100);

      // Previous minus two - SR2
      display.drawRect(shi - (3 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
      display.fillRect(shi - (3 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
      display.setCursor(shi - (3 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
      display.print(int(current_frequency - 2) / 100);
      display.print(".");
      if (int(current_frequency - 2)%100 < 10)
         display.print("0");
      display.print(int(current_frequency - 2) % 100);

      // Previous minus three - SR3
      if (offset > 1) {
        display.drawRect(shi - (4 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
        display.fillRect(shi - (4 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
        display.setCursor(shi - (4 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
        display.print(int(current_frequency - 3) / 100);
        display.print(".");
        if (int(current_frequency - 3)%100 < 10)
           display.print("0");
        display.print(int(current_frequency - 3) % 100);
      }

      // Previous minus four - SR4
      if (offset > 2) {
        display.drawRect(shi - (5 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
        display.fillRect(shi - (5 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
        display.setCursor(shi - (5 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
        display.print(int(current_frequency - 4) / 100);
        display.print(".");
        if (int(current_frequency - 4)%100 < 10)
           display.print("0");
        display.print(int(current_frequency - 4) % 100);
      }

      // Previous minus five - SR5
      if (offset > 3) {
        display.drawRect(shi - (6 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
        display.fillRect(shi - (6 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
        display.setCursor(shi - (6 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
        display.print(int(current_frequency - 5) / 100);
        display.print(".");
        if (int(current_frequency - 5)%100 < 10)
           display.print("0");
        display.print(int(current_frequency - 5) % 100);
      }
      // Previous minus six - SR6
      if (offset > 4) {
        display.drawRect(shi - (7 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
        display.fillRect(shi - (7 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
        display.setCursor(shi - (7 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
        display.print(int(current_frequency - 6) / 100);
        display.print(".");
        if (int(current_frequency - 6)%100 < 10)
           display.print("0");
        display.print(int(current_frequency - 6) % 100);
      }

      // Draw the gauge line
      display.drawFastVLine(79,25,30,ST7735_RED);
      display.drawFastVLine(80,25,30,ST7735_RED);
      display.drawFastVLine(81,25,30,ST7735_RED);
      display.drawFastVLine(82,25,30,ST7735_RED);

      shi = shi + offset;
  }
}

void shift_lower(int offset) {   // sli decreases

  Serial.print("In shift lower - current: ");
  Serial.print(current_frequency);
  Serial.print(" previous: ");
  Serial.print(previous_frequency);
  Serial.print(" shift: ");
  Serial.println(shift_in_frequency);

  sli = 0;
  while(sli >= 0 - ((offset * box_width) + 25)) {

      // Starting box
      display.drawRect(sli + box_width,box_y_coord,box_width,box_height,ST7735_BLACK);
      display.fillRect(sli + box_width + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
      display.setCursor(sli + (box_width) + 6,box_y_coord + (box_height / 2) - 6);
      display.print(int(current_frequency) / 100);
      display.print(".");
      if (int(current_frequency)%100 < 10)
         display.print("0");
      display.print(int(current_frequency) % 100);

      // Next plus one - SL1
      display.drawRect(sli + (2 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
      display.fillRect(sli + (2 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
      display.setCursor(sli + (2 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
      display.print(int(current_frequency + 1) / 100);
      display.print(".");
      if (int(current_frequency + 1)%100 < 10)
         display.print("0");
      display.print(int(current_frequency + 1)%100);

      // Next plus two - SL1
      display.drawRect(sli + (3 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
      display.fillRect(sli + (3 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
      display.setCursor(sli + (3 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
      display.print(int(current_frequency + 2) / 100);
      display.print(".");
      if (int(current_frequency + 2)%100 < 10)
         display.print("0");
      display.print(int(current_frequency + 2) % 100);

      // Next plus three - SL2
      if (offset > 1) {
        display.drawRect(sli + (4 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
        display.fillRect(sli + (4 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
        display.setCursor(sli + (4 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
        display.print(int(current_frequency + 3) / 100);
        display.print(".");
        if (int(current_frequency + 3)%100 < 10)
           display.print("0");
        display.print(int(current_frequency + 3) % 100);
      }
      // Next plus four - SL3
      if (offset > 2) {
        display.drawRect(sli + (5 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
        display.fillRect(sli + (5 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
        display.setCursor(sli + (5 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
        display.print(int(current_frequency + 4) / 100);
        display.print(".");
        if (int(current_frequency + 4)%100 < 10)
           display.print("0");
        display.print(int(current_frequency + 4) % 100);
      }
      // Next plus five - SL4
      if (offset > 3) {
        display.drawRect(sli + (6 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
        display.fillRect(sli + (6 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
        display.setCursor(sli + (6 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
        display.print(int(current_frequency + 5) / 100);
        display.print(".");
        if (int(current_frequency + 5)%100 < 10)
           display.print("0");
        display.print(int(current_frequency + 5) % 100);
      }
      // Next plus six - SL5
      if (offset > 4) {
        display.drawRect(sli + (7 * box_width),box_y_coord,box_width,box_height,ST7735_BLACK);
        display.fillRect(sli + (7 * box_width) + 1,box_y_coord + 1,box_width - 2,box_height - 2,ST7735_WHITE);
        display.setCursor(sli + (7 * box_width) + 6,box_y_coord + (box_height / 2) - 6);
        display.print(int(current_frequency + 6) / 100);
        display.print(".");
        if (int(current_frequency + 6)%100 < 10)
           display.print("0");
        display.print(int(current_frequency + 6) % 100);
      }

      display.drawFastVLine(79,25,30,ST7735_RED);
      display.drawFastVLine(80,25,30,ST7735_RED);
      display.drawFastVLine(81,25,30,ST7735_RED);
      display.drawFastVLine(82,25,30,ST7735_RED);

      sli = sli - offset; // was box_speed
  }
  
}

That to me reads as though if the frequency doesn't change then it should stay where it is. But then you say that is wrong.

Your description is very confusing.

OK . Let say current is 5000 and previous is 4998. The shift (current - previous) is 2 so the shift_higher procedure is invoked.

Right, but it isn't clear what you expect to see. What should the dial indicate? If the dial should point to the current frequency then forget all that offset stuff and calculating to the last frequency, just put the pointer on the current frequency. In your example do you want the dial to end up at 5000 or 4998?

But maybe that isn't what you want. Maybe you want to see the delta, so in your example the pointer should point to 2.

Instead of talking about how the code should work, describe what you want to see on the dial where it makes sense. Thwn we can look at what the code does to see how to make that happen. Figuring it all out from broken code is an exercise in futility.

In addition if the current -= previous then you are correct. However because the display always shows the previous reading, I'd like it to move to the current reading, either by fixing the first problem outlined or by a means of "forcing" it so.

Slow down a little. What do you mean there. This makes zero sense. What is -= in this sense mean to you?

To answer your first point the dial should move two divisions that is after displaying the 5000 figure it should then move to the 4998 figure. All that works. I've tried to upload the video but its an MP4 file and won't upload.

= means the same as

Sorry got those the wrong way round. Should be displays shows 4998 then should move to show 5000. Apologies

Then why does it matter where the needle was before or wht the previous frequency was? Just point the dial to 5000.

Maybe I still misunderstand.

If previous frequency was 4995 and the new frequency is 5000 then where would the dial start and end.

Same question if the previous was 5000 and the new is 4995?

Same question if the new frequency is 4998 and the old frequency was also 4998.

Ok maybe this will help - see image.


The current frequency 4999) has just been derived and will enter the shift_lower procedure (the values you see are also mirrored) in the Serial print output) However on exit from that procedure it is showing the previous value on the dial and not the current. In a similar way if the current and previous values were reversed the display would show Previous as 4999 and Current as 5003 with a Shift = +4.
I believe if this could be corrected your final point would also be solved too.

In terms of movement of the screen display I would expect the 50.03 to move to the right, the 50.02 to move to the 50.03 an d so on until 49.99 appears on the middle box. And this movement process does work (in both directions) . However the problem remains in that the display always shows the previous value and not the current value.

I give up. Maybe someone else can understand you. I still don't know how the screen should change.

What would be the difference when displaying 5000 if the previous was 4998 or if it was 5002. At the end the screen would look the same. So don't worry what the old one was.

Or explain it NOT IN TERMS OF CODE but in simple terms of what you want to see.

Ok one last try. At the top of the main loop I obtain the current frequency (lets say 5000). I have already at the bottom of the main loop stored the previous frequency of 4998. After comparing the two there is a shift of plus 2.
The sketch then enters the shift higher procedure. I would expect to see the middle box change to the left by one decrement , then by another so from 4998 to 4999 to 5000. However what is happening is the screen is not moving even though the debugging values show the correct current,previous and shift values. The screen shows the middle box as 49.98 and does not move to 50.00. BUT when the next current value is obtained THEN it moves to 50.00. In other words it's always one readng behind.

Sorry my bad, decrement should increment

And you are still describing how you think the code should work and not what you want to see on the dial in terms of how it should look and behave. I still don't understand why you need to know anything about the previous frequency.

I'm going to mute this thread. Maybe someone else can figure it out.

I'm sorry you're unable to help me and I thank you for your time and input. If only I were able to upload the video it would be immediately obvious what the issue is. If anyone wants to email me I'll gladly send the video.

I've solved the problem. It's because I was using the wrong value in the shift routines, ie I was using current_frequency instead of previous_frequency. After all, I want to know what the frequency has changed FROM not TO :slight_smile: On changing that and swapping the calls to higher and lower around, it all works perfectly. I will close the topic.