Issues with variable pointers

I'm making a UI for my AD9850 DDS with a standard 16x2 lcd screen and a 4x4 keypad. I have been having issues with variable pointers:

void screenBackspace(unsigned long &var) {
  var -= var % 10; // Remove last digit to prevent any division errors
  var /= 10; // Divide by ten
  lcd.setCursor(1,1);
  lcd.print("               "); // 15 spaces - clear bottom line (except for '>')
  lcd.setCursor(1,1);
  if (var != 0) {lcd.print(var);}
  keyHoldTimer.setInterval(1500);
  keyHoldTimer.reset();
  keyHoldTimer.enable();
}

void screenInput(unsigned long &var, KeypadEvent key) {
  int tkey = key - '0';
  var = var * 10;
  var = var + tkey;
  if (var > bwLimit) var = bwLimit; // Restrict bandwidth to pre-set limit
  lcd.setCursor(1,1);
  lcd.print(var);
  keyHoldTimer.setInterval(1500);
  keyHoldTimer.reset();
  keyHoldTimer.enable(); // Start key hold timer
}

void keyHold() {
  unsigned long *var;
  if (kpd.getState() == HOLD) {
    switch (currentScreen) {
      case s_staticFreq: {
        *var = &staticFreq;
        break;
      }
      
      case s_sweepFreqStart: {
        *var = &sweepFreqStart;
        break;
      }
      
      case s_sweepFreqEnd: {
        *var = &sweepFreqEnd;
        break;
      }
      
      case s_sweepStep: {
        *var = &sweepStep;
        break;
      }
    }
    
    switch (currentKey) {
      case '*': {
        screenBackspace(*var);
        break;
      }
      
      case '#':
      case 'A':
      case 'B':
      case 'C':
      case 'D': {
        keyHoldTimer.disable(); // Do nothing for non-numerical keys (apart from * which is backspace);
        break;
      }
      
      default: { // Number keys
        screenInput(*var, currentKey);
        break;
      }
    }
  }
  else {
    keyHoldTimer.disable();
  }
}

This is the bit I'm having trouble with. screenInput() and screenBackspace() work fine, but when compiling I get the following error message:
error: invalid conversion from 'long unsigned int*' to 'long unsigned int'
I have used this page as my reference.
Any ideas as to what is going wrong?

  unsigned long *var;

Every single use of this variable is as a variable, not a pointer. Why is var declared to be a pointer?

Any ideas as to what is going wrong?

There is a lot of code missing. Things that explain why you are storing addresses in variables, etc. The line number that generates the error is also missing.

The first line number is 132 - ‘*var = &staticFreq’.
I didn’t post the whole sketch because it’s quite big, but here you go:

#include <TimedAction.h>
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <String.h>

const byte ROWS = 4;
const byte COLS = 4;
const String fversion = "v0.1";
const unsigned long bwLimit = 50000000;
const int lcdTimer = 1;
enum Screen {s_root, s_staticFreq, s_staticFreqOutput, s_sweepFreqStart, s_sweepFreqEnd, s_sweepStep};

char keys[ROWS][COLS] = {
  {'*', '0', '#', 'D'},
  {'7', '8', '9', 'C'},
  {'4', '5', '6', 'B'},
  {'1', '2', '3', 'A'} };
byte rowPins[ROWS] = {44, 45, 46, 47};
byte colPins[COLS] = {43, 42, 41, 40};
unsigned long staticFreq;
unsigned long sweepFreqStart;
unsigned long sweepFreqEnd;
unsigned long sweepStep;
Screen currentScreen = s_root;
int lcdScrollLength = 0;
String lcdStaticTopLine;
int lcdScrollDelay = 1000; // Delay while screen has reached either end of the scroll cycle
int lcdScrollLetterDelay = 150; // Delay between each letter
int lcdScrollStage = 0;
int lcdPositionCounter = 0;
boolean lcdPositionCounterSet = false;
int keyHoldDelay = 500; // When a key is held, numbers are input every keyHoldDelay milliseconds.

TimedAction lcdScrollTimer = TimedAction(lcdScrollDelay, lcdScrollEvent);
TimedAction keyHoldTimer = TimedAction(keyHoldDelay, keyHold);
LiquidCrystal lcd(22, 23, 24, 25, 26, 27);
Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
char currentKey;

void setup() {
  lcdScrollTimer.disable();
  keyHoldTimer.disable();
  kpd.addEventListener(updateScreen);
  kpd.setHoldTime(400);
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("AD9850 DDS");
  lcd.setCursor(0,1);
  lcd.print("Firmware ");
  lcd.print(fversion);
  delay(2000);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("A: Static freq");
  lcd.setCursor(0,1);
  lcd.print("B: Sweep freqs");
}

void loop() {
  kpd.getKey();
  lcdScrollTimer.check();
  keyHoldTimer.check();
}

void lcdScrollEvent() {
  Serial.println("lcdScrollEvent called");
  switch (lcdScrollStage) {
    case 0: {
      if (!lcdPositionCounterSet) {
        lcdPositionCounter = 0;
        lcdPositionCounterSet = true;
      }
      if (lcdPositionCounter >= lcdScrollLength) {
        lcdScrollStage += 1;
        lcdScrollTimer.setInterval(lcdScrollDelay);
        break;
      }
      lcd.scrollDisplayLeft();
      lcd.setCursor(lcdPositionCounter + 1, 0);
      lcd.print(lcdStaticTopLine);
      lcdPositionCounter++;
      lcdScrollTimer.setInterval(lcdScrollLetterDelay); // TEH MAGIC!
      break;
    }
    
    case 1: {
      for (lcdPositionCounter = 0; lcdPositionCounter < lcdScrollLength; lcdPositionCounter++) {
        lcd.scrollDisplayRight();
      }
      lcdScrollStage -= 1;
      // Lcd scroll timer already set: no need to do so again here
      lcdPositionCounterSet = false;
      lcd.setCursor(0,0);
      lcd.print(lcdStaticTopLine);
      break;
    }
  }
}

void lcdScroll(int length, String topLine) {
  lcdScrollTimer.setInterval(lcdScrollDelay); // Reset interval
  lcdScrollTimer.reset(); // Reset timer
  lcdPositionCounter = 0; // Reset position
  lcdScrollLength = length;
  lcdStaticTopLine = topLine;
  lcdScrollTimer.enable();
}

void noLcdScroll() {
  lcdScrollTimer.disable();
}

void screenBackspace(unsigned long &var) {
  var -= var % 10; // Remove last digit to prevent any division errors
  var /= 10; // Divide by ten
  lcd.setCursor(1,1);
  lcd.print("               "); // 15 spaces - clear bottom line (except for '>')
  lcd.setCursor(1,1);
  if (var != 0) {lcd.print(var);}
  keyHoldTimer.setInterval(1500);
  keyHoldTimer.reset();
  keyHoldTimer.enable();
}

void keyHold() {
  unsigned long *var;
  if (kpd.getState() == HOLD) {
    switch (currentScreen) {
      case s_staticFreq: {
        *var = &staticFreq;
        break;
      }
      
      case s_sweepFreqStart: {
        *var = &sweepFreqStart;
        break;
      }
      
      case s_sweepFreqEnd: {
        *var = &sweepFreqEnd;
        break;
      }
      
      case s_sweepStep: {
        *var = &sweepStep;
        break;
      }
    }
    
    switch (currentKey) {
      case '*': {
        screenBackspace(*var);
        break;
      }
      
      case '#':
      case 'A':
      case 'B':
      case 'C':
      case 'D': {
        keyHoldTimer.disable(); // Do nothing for non-numerical keys (apart from * which is backspace);
        break;
      }
      
      default: { // Number keys
        screenInput(*var, currentKey);
        break;
      }
    }
  }
  else {
    keyHoldTimer.disable();
  }
}

void screenInput(unsigned long &var, KeypadEvent key) {
  int tkey = key - '0';
  var = var * 10;
  var = var + tkey;
  if (var > bwLimit) var = bwLimit; // Restrict bandwidth to pre-set limit
  lcd.setCursor(1,1);
  lcd.print(var);
  keyHoldTimer.setInterval(1500);
  keyHoldTimer.reset();
  keyHoldTimer.enable(); // Start key hold timer
}

void updateScreen(KeypadEvent key) {
  currentKey = key;
  
  if (kpd.getState() == PRESSED) {
    if (key == 'C') {
      noLcdScroll();
      lcd.clear();
      lcd.noBlink();
      lcd.setCursor(0,0);
      lcd.print("A: Static freq");
      lcd.setCursor(0,1);
      lcd.print("B: Sweep freqs");
      staticFreq = 0;
      sweepFreqStart = 0;
      sweepFreqEnd = 0;
      sweepStep = 0;
      currentScreen = s_root;
    }
    
    switch (currentScreen) {
      case s_root: {
        switch (key) {
          case 'A': {
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Enter frequency");
            lcd.setCursor(0,1);
            lcd.print(">");
            lcd.blink();
            currentScreen = s_staticFreq;
            break;
          }
          case 'B': {
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Enter start freq");
            lcd.setCursor(0,1);
            lcd.print(">");
            lcd.blink();
            currentScreen = s_sweepFreqStart;
            break;
          }
        }
        break;
      }
    
      case s_staticFreq: {
        switch (key) {
          case '*': {
            screenBackspace(staticFreq);
            break;
          }
          
          case '#': {
            if (staticFreq > 0) {
              lcd.noBlink();
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print("Beginning output");
              lcd.setCursor(0,1);
              lcd.print("Frequency(Hz): ");
              lcd.print(staticFreq);
              lcd.home();
              String scrollLen = String(staticFreq);
              lcdScroll(scrollLen.length() - 1, "Beginning output");            
              currentScreen = s_staticFreqOutput;
              
              // Set AD9850 module here
              
            }
            break;
          }
          
          case 'A':
          case 'B':
          case 'C':
          case 'D': {break;}
          
          default: {
            screenInput(staticFreq, key);
            break;
          }
        }
        break;
      }
      
      case s_sweepFreqStart: {
        switch (key) {
          case '*': {
            screenBackspace(sweepFreqStart);
            break;
          }
          
          case '#': {
            if (sweepFreqStart > 0) {
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print("Enter end freq");
              lcd.setCursor(0,1);
              lcd.print(">");
              lcd.blink();
              currentScreen = s_sweepFreqEnd;
            }
            break;
          }
          
          case 'A':
          case 'B':
          case 'C':
          case 'D': {break;}
          
          default: {
            screenInput(sweepFreqStart, key);
            break;
          }
        }
        break;
      }
    }
  }
}
  kpd.addEventListener(updateScreen);

So, when a key is pressed, you want updateScreen() to be called.

  kpd.getKey();

So, what's this useless code for? See if a key is pressed, but don't bother keeping that key. So, why bother?

void screenBackspace(unsigned long &var) {

Do you really want the value passed to this routine to be modified in the calling function?

void keyHold() {
  unsigned long *var;
        *var = &staticFreq;
         *var = &sweepFreqStart;
         *var = &sweepFreqEnd;
         *var = &sweepStep;

You are storing addresses in the memory location that var points to.

        screenBackspace(*var);

Then, you expect this function to divide the address by 10. How can you expect that to work?

var should not be a pointer, and screenBackspace() should not be a void function, and should not take a reference.

screenBackspace should be an unsigned long function, taking an unsigned long VALUE, and returning the modified value.

Then, keyHold() needs a complete rewrite.

kpd.getKey() is needed in the loop function because otherwise (for reasons beyond me) the event handler for keypresses doesn't get called. Thanks for your help, I will rewrite the functions + keyHold now.

Thanks, PaulS: it works well now :slight_smile:
For anyone else who has the same (unlikely niche) problem, here is my code:

#include <TimedAction.h>
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <String.h>

const byte ROWS = 4;
const byte COLS = 4;
const String fversion = "v0.1";
const unsigned long bwLimit = 50000000;
const int lcdTimer = 1;
enum Screen {s_root, s_staticFreq, s_staticFreqOutput, s_sweepFreqStart, s_sweepFreqEnd, s_sweepStep};

char keys[ROWS][COLS] = {
  {'*', '0', '#', 'D'},
  {'7', '8', '9', 'C'},
  {'4', '5', '6', 'B'},
  {'1', '2', '3', 'A'} };
byte rowPins[ROWS] = {44, 45, 46, 47};
byte colPins[COLS] = {43, 42, 41, 40};
unsigned long staticFreq;
unsigned long sweepFreqStart;
unsigned long sweepFreqEnd;
unsigned long sweepStep;
Screen currentScreen = s_root;
int lcdScrollLength = 0;
String lcdStaticTopLine;
int lcdScrollDelay = 1000; // Delay while screen has reached either end of the scroll cycle
int lcdScrollLetterDelay = 150; // Delay between each letter
int lcdScrollStage = 0;
int lcdPositionCounter = 0;
boolean lcdPositionCounterSet = false;
int keyHoldDelay = 200; // When a key is held, numbers are input every keyHoldDelay milliseconds.
int initialKeyHoldDelay = 1500; // Time you must hold a key before it will print several characters

TimedAction lcdScrollTimer = TimedAction(lcdScrollDelay, lcdScrollEvent);
TimedAction keyHoldTimer = TimedAction(initialKeyHoldDelay, keyHold);
LiquidCrystal lcd(22, 23, 24, 25, 26, 27);
Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
char currentKey;

void setup() {
  lcdScrollTimer.disable();
  keyHoldTimer.disable();
  kpd.addEventListener(updateScreen);
  kpd.setHoldTime(400);
  // Serial.begin(9600);
  // Debug only
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("AD9850 DDS");
  lcd.setCursor(0,1);
  lcd.print("Firmware ");
  lcd.print(fversion);
  delay(2000);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("A: Static freq");
  lcd.setCursor(0,1);
  lcd.print("B: Sweep freqs");
}

void loop() {
  kpd.getKey();
  lcdScrollTimer.check();
  keyHoldTimer.check();
}

void lcdScrollEvent() {
  Serial.println("lcdScrollEvent called");
  switch (lcdScrollStage) {
    case 0: {
      if (!lcdPositionCounterSet) {
        lcdPositionCounter = 0;
        lcdPositionCounterSet = true;
      }
      if (lcdPositionCounter >= lcdScrollLength) {
        lcdScrollStage += 1;
        lcdScrollTimer.setInterval(lcdScrollDelay);
        break;
      }
      lcd.scrollDisplayLeft();
      lcd.setCursor(lcdPositionCounter + 1, 0);
      lcd.print(lcdStaticTopLine);
      lcdPositionCounter++;
      lcdScrollTimer.setInterval(lcdScrollLetterDelay); // TEH MAGIC!
      break;
    }
    
    case 1: {
      for (lcdPositionCounter = 0; lcdPositionCounter < lcdScrollLength; lcdPositionCounter++) {
        lcd.scrollDisplayRight();
      }
      lcdScrollStage -= 1;
      // Lcd scroll timer already set: no need to do so again here
      lcdPositionCounterSet = false;
      lcd.setCursor(0,0);
      lcd.print(lcdStaticTopLine);
      break;
    }
  }
}

void lcdScroll(int length, String topLine) {
  lcdScrollTimer.setInterval(lcdScrollDelay); // Reset interval
  lcdScrollTimer.reset(); // Reset timer
  lcdPositionCounter = 0; // Reset position
  lcdScrollLength = length;
  lcdStaticTopLine = topLine;
  lcdScrollTimer.enable();
}

void noLcdScroll() {
  lcdScrollTimer.disable();
}

unsigned long screenInput(unsigned long var, KeypadEvent key) {
  int tkey = key - '0';
  var = var * 10;
  var = var + tkey;
  if (var > bwLimit) var = bwLimit; // Restrict bandwidth to pre-set limit
  lcd.setCursor(1,1);
  lcd.print(var);
  keyHoldTimer.reset();
  keyHoldTimer.enable(); // Start key hold timer
  return var;
}

unsigned long screenBackspace(unsigned long var) {
  var -= var % 10; // Remove last digit to prevent any division errors
  var /= 10; // Divide by ten
  lcd.setCursor(1,1);
  lcd.print("               "); // 15 spaces - clear bottom line (except for '>')
  lcd.setCursor(1,1);
  if (var != 0) {lcd.print(var);}
  keyHoldTimer.reset();
  keyHoldTimer.enable();
  return var;
}

void keyHold() { 
  keyHoldTimer.setInterval(keyHoldDelay);
  unsigned long var;
  if (kpd.getState() == HOLD) {
    switch (currentKey) {
      case '*': {
        switch (currentScreen) {
          case s_staticFreq: {
            staticFreq = screenBackspace(staticFreq);
            break;
          }
          case s_sweepFreqStart: {
            sweepFreqStart = screenBackspace(sweepFreqStart);
            break;
          }
          case s_sweepFreqEnd: {
            sweepFreqEnd = screenBackspace(sweepFreqEnd);
            break;
          }
          case s_sweepStep: {
            sweepStep = screenBackspace(sweepStep);
            break;
          }
        }
        break;
      }
      
      case '#':
      case 'A':
      case 'B':
      case 'C':
      case 'D': {
        keyHoldTimer.disable(); // Cancel timer for non-numerical keys (apart from * which is backspace) otherwise it would continue indefinitely
        break;
      }
      
      default: { // Number keys
        switch (currentScreen) {
          case s_staticFreq: {
            staticFreq = screenInput(staticFreq, currentKey);
            break;
          }
          case s_sweepFreqStart: {
            sweepFreqStart = screenInput(sweepFreqStart, currentKey);
            break;
          }
          case s_sweepFreqEnd: {
            sweepFreqEnd = screenInput(sweepFreqEnd, currentKey);
            break;
          }
          case s_sweepStep: {
            sweepStep = screenInput(sweepStep, currentKey);
            break;
          }
        }
        break;
      }
    }
  }
  else {
    keyHoldTimer.disable();
    keyHoldTimer.setInterval(initialKeyHoldDelay);
  }
}

void updateScreen(KeypadEvent key) {
  currentKey = key;
  
  if (kpd.getState() == PRESSED) {
    if (key == 'C') {
      noLcdScroll();
      lcd.clear();
      lcd.noBlink();
      lcd.setCursor(0,0);
      lcd.print("A: Static freq");
      lcd.setCursor(0,1);
      lcd.print("B: Sweep freqs");
      staticFreq = 0;
      sweepFreqStart = 0;
      sweepFreqEnd = 0;
      sweepStep = 0;
      currentScreen = s_root;
    }
    
    switch (currentScreen) {
      case s_root: {
        switch (key) {
          case 'A': {
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Enter frequency");
            lcd.setCursor(0,1);
            lcd.print(">");
            lcd.blink();
            currentScreen = s_staticFreq;
            break;
          }
          case 'B': {
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Enter start freq");
            lcd.setCursor(0,1);
            lcd.print(">");
            lcd.blink();
            currentScreen = s_sweepFreqStart;
            break;
          }
        }
        break;
      }
    
      case s_staticFreq: {
        switch (key) {
          case '*': {
            staticFreq = screenBackspace(staticFreq);
            break;
          }
          
          case '#': {
            if (staticFreq > 0) {
              lcd.noBlink();
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print("Beginning output");
              lcd.setCursor(0,1);
              lcd.print("Frequency(Hz): ");
              lcd.print(staticFreq);
              lcd.home();
              String scrollLen = String(staticFreq);
              lcdScroll(scrollLen.length() - 1, "Beginning output");            
              currentScreen = s_staticFreqOutput;
              
              // Set AD9850 module here
              
            }
            break;
          }
          
          case 'A':
          case 'B':
          case 'C':
          case 'D': {break;}
          
          default: {
            staticFreq = screenInput(staticFreq, key);
            break;
          }
        }
        break;
      }
      
      case s_sweepFreqStart: {
        switch (key) {
          case '*': {
            sweepFreqStart = screenBackspace(sweepFreqStart);
            break;
          }
          
          case '#': {
            if (sweepFreqStart > 0) {
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print("Enter end freq");
              lcd.setCursor(0,1);
              lcd.print(">");
              lcd.blink();
              currentScreen = s_sweepFreqEnd;
            }
            break;
          }
          
          case 'A':
          case 'B':
          case 'C':
          case 'D': {break;}
          
          default: {
            sweepFreqStart = screenInput(sweepFreqStart, key);
            break;
          }
        }
        break;
      }
    }
  }
}