Null Pointer help and some guidance with a working EEPROM write Processing sketch

Hello,
This is my first post. I apologize if I’m not adhering to the syntax for submitting questions if I messed it up. I created a working Arduino nano sketch that works in combination with a Processing sketch to read 16 floating point values from EEPROM with a controlP5 button, then be editable in text boxes, and then be written back to the EEPROM bytes 0 - 64 with another controlP5 button.

  1. They both work, compile, and the program functions.
  2. I’m getting a null pointer exception and I know exactly where it throws the exception , but I’m a noob and after hours of trying to figure out how to fix it, I need some real guidance on how to fix the null pointers and any general guidance on how to make my code better, shorter, less clunky would be appreciated. I am also ok with reimbursing someone via paypal for their time in order to get this project completed. Arduino Nano code:
#include <EEPROM.h>


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


void loop() {
  float f = 0.00f;   //Create null aa (0)
  float g = 0.00f;   // ab (4)
  float h = 0.00f;   // ba (8)
  float i = 0.00f;   // bb (12)
  float j = 0.00f;   // ca (16)
  float k = 0.00f;   // cb (20)
  float l = 0.00f;   // da (24)
  float m = 0.00f;   // db (28)
  float n = 0.00f;   // ea (32)
  float o = 0.00f;   // eb (36)
  float p = 0.00f;   // fa (40)
  float q = 0.00f;   // fb (44)
  float r = 0.00f;   // ga (48)
  float s = 0.00f;   // gb (52)
  float t = 0.00f;   // ha (56)
  float u = 0.00f;   // hb (60)
  int eeAddressaa = 0; //EEPROM address aa (0)
  int eeAddressab = 4; //EEPROM address ab (4)
  int eeAddressba = 8; //EEPROM address ba (8)
  int eeAddressbb = 12; //EEPROM address bb (12)
  int eeAddressca = 16; //EEPROM address ca (16)
  int eeAddresscb = 20; //EEPROM address cb (20)
  int eeAddressda = 24; //EEPROM address da (24)
  int eeAddressdb = 28; //EEPROM address db (28)
  int eeAddressea = 32; //EEPROM address ea (32)
  int eeAddresseb = 36; //EEPROM address eb (36)
  int eeAddressfa = 40; //EEPROM address fa (40)
  int eeAddressfb = 44; //EEPROM address fb (44)
  int eeAddressga = 48; //EEPROM address ga (48)
  int eeAddressgb = 52; //EEPROM address gb (52)
  int eeAddressha = 56; //EEPROM address ha (56)
  int eeAddresshb = 60; //EEPROM address hb (60)
  
  if(Serial.available()){
  int val = Serial.read();
  if(val == 1){


  //Get the float data from the EEPROM at position 'eeAddress'
  EEPROM.get(eeAddressaa, f );
  EEPROM.get(eeAddressab, g);
  EEPROM.get(eeAddressba, h );
  EEPROM.get(eeAddressbb, i);
  EEPROM.get(eeAddressca, j);
  EEPROM.get(eeAddresscb, k);
  EEPROM.get(eeAddressda, l);
  EEPROM.get(eeAddressdb, m);
  EEPROM.get(eeAddressea, n);
  EEPROM.get(eeAddresseb, o);
  EEPROM.get(eeAddressfa, p);
  EEPROM.get(eeAddressfb, q);
  EEPROM.get(eeAddressga, r);
  EEPROM.get(eeAddressgb, s);
  EEPROM.get(eeAddressha, t);
  EEPROM.get(eeAddresshb, u);
  Serial.println(f, 2 );  //This may print 'ovf, nan' if the data inside the EEPROM is not a valid float.
  Serial.println(g, 2);
  Serial.println(h, 2);
  Serial.println(i, 2);
  Serial.println(j, 2);
  Serial.println(k, 2);
  Serial.println(l, 2);
  Serial.println(m, 2);
  Serial.println(n, 2);
  Serial.println(o, 2);
  Serial.println(p, 2);
  Serial.println(q, 2);
  Serial.println(r, 2);
  Serial.println(s, 2);
  Serial.println(t, 2);
  Serial.println(u, 2); 
  }


else if(val == 2){
    float aafloat;
    float abfloat;
    float bafloat;
    float bbfloat;
    float cafloat;
    float cbfloat;
    float dafloat;
    float dbfloat;
    float eafloat;
    float ebfloat;
    float fafloat;
    float fbfloat;
    float gafloat;
    float gbfloat;
    float hafloat;
    float hbfloat;
    int nl = 10;// ASCII code for carriage return
    aafloat = Serial.parseFloat();
    abfloat = Serial.parseFloat();
    bafloat = Serial.parseFloat();
    bbfloat = Serial.parseFloat();
    cafloat = Serial.parseFloat();
    cbfloat = Serial.parseFloat();
    dafloat = Serial.parseFloat();
    dbfloat = Serial.parseFloat();
    eafloat = Serial.parseFloat();
    ebfloat = Serial.parseFloat();
    fafloat = Serial.parseFloat();
    fbfloat = Serial.parseFloat();
    gafloat = Serial.parseFloat();
    gbfloat = Serial.parseFloat();
    hafloat = Serial.parseFloat();
    hbfloat = Serial.parseFloat();
    EEPROM.put(eeAddressaa, aafloat);
    EEPROM.put(eeAddressab, abfloat);
    EEPROM.put(eeAddressba, bafloat);
    EEPROM.put(eeAddressbb, bbfloat);
    EEPROM.put(eeAddressca, cafloat);
    EEPROM.put(eeAddresscb, cbfloat);
    EEPROM.put(eeAddressda, dafloat);
    EEPROM.put(eeAddressdb, dbfloat);
    EEPROM.put(eeAddressea, eafloat);
    EEPROM.put(eeAddresseb, ebfloat);
    EEPROM.put(eeAddressfa, fafloat);
    EEPROM.put(eeAddressfb, fbfloat);
    EEPROM.put(eeAddressga, gafloat);
    EEPROM.put(eeAddressgb, gbfloat);
    EEPROM.put(eeAddressha, hafloat);
    EEPROM.put(eeAddresshb, hbfloat);
  }}
  }

Processing Sketch code:<

import controlP5.*;
import processing.serial.*;
import static javax.swing.JOptionPane.*;

//This is needed for the COM selection GUI
final boolean debug = true;

//Define our Serial Port
Serial myPort;

ControlP5 cp5;

//Let's define Text Areas 
Textarea slopeTextarea;
Textarea interceptTextarea;
//Now our Text fields 8 channels a - h each with 2 values for a total of 16
Textfield aaTextarea;
Textfield abTextarea;
Textfield baTextarea;
Textfield bbTextarea;
Textfield caTextarea;
Textfield cbTextarea;
Textfield daTextarea;
Textfield dbTextarea;
Textfield eaTextarea;
Textfield ebTextarea;
Textfield faTextarea;
Textfield fbTextarea;
Textfield gaTextarea;
Textfield gbTextarea;
Textfield haTextarea;
Textfield hbTextarea;

//Set our font
PFont font;

//Let's define our 16 input Strings and 16 "trimmed" Strings and set as null for now
String aaString = null;
String abString = null;
String baString = null;
String bbString = null; 
String caString = null; 
String cbString = null; 
String daString = null; 
String dbString = null; 
String eaString = null;  
String ebString = null;  
String faString = null;  
String fbString = null;  
String gaString = null; 
String gbString = null;  
String haString = null; 
String hbString = null; 
String aatrim = null; //a variable to store stripped data before displaying in TextFields
String abtrim = null;
String batrim = null;
String bbtrim = null;
String catrim = null;
String cbtrim = null;
String datrim = null;
String dbtrim = null;
String eatrim = null;
String ebtrim = null;
String fatrim = null;
String fbtrim = null;
String gatrim = null;
String gbtrim = null;
String hatrim = null;
String hbtrim = null;

//This is used for parsing data traveling from the Arduino to Processing (READ CONFIG stuff)
int nl = 10;// ASCII code for carriage return

//Into our Setup
void setup(){
  size (800,450);
//Uncomment the line below to not use the COM selection GUI and "hard code" a COM Port
  //myPort = new Serial(this, "COM5", 115200);
  background(color(20,20,20));
  cp5= new ControlP5(this);
  font = createFont( "Lucida Sans Demibold", 12);
 
//GUI to select COM Port
  String COMx, COMlist = "";
/*
  Other setup code goes here - I put this at
  the end because of the try/catch structure.
*/
  try {
    if(debug) printArray(Serial.list());
    int i = Serial.list().length;
    if (i != 0) {
      if (i >= 2) {
        // need to check which myPort the inst uses -
        // for now we'll just let the user decide
        for (int j = 0; j < i;) {
          COMlist += char(j+'A') + " = " + Serial.list()[j];
          if (++j < i) COMlist += ",  ";
        }
        COMx = showInputDialog("Which COM myPort is correct? (A,B,..):\n"+COMlist);
        if (COMx == null) exit();
        if (COMx.isEmpty()) exit();
        i = int(COMx.toLowerCase().charAt(0) - 'a') + 1;
      }
      String myPortName = Serial.list()[i-1];
      if(debug) println(myPortName);
      myPort = new Serial(this, myPortName, 115200); // change baud rate to your liking
      myPort.bufferUntil('\n'); // buffer until CR/LF appears, but not required..
    }
    else {
      showMessageDialog(frame,"Device is not connected to the PC");
      exit();
    }
  }
  catch (Exception e)
  { //Print the type of error
    showMessageDialog(frame,"COM myPort is not available (may\nbe in use by another program)");
    println("Error:", e);
    exit();
  }
//End of COM selection GUI

//Lets make our Buttons
//aabutton
 cp5.addButton("READ").setValue(0).setCaptionLabel("Read Config").setPosition(275,100).setSize(100,50).setColorBackground(color(230,5,0)).setColorActive(color(255,112,3)).setColorForeground(color(255,0,0)).setFont (font);
//abbutton
cp5.addButton("SEND").setValue(0).setCaptionLabel("Send Config").setPosition(400,100).setSize(100,50).setColorBackground(color(230,5,0)).setColorActive(color(255,112,3)).setColorForeground(color(255,0,0)).setFont (font);

//Let's make our 2 Text Areas and 16 Text Fields   
//Add Text Field for "Slope"
  slopeTextarea = cp5.addTextarea("slope")
                  .setPosition(10,350)
                  .setSize(55,25)
                  .setLineHeight(14)
                  .setColor(color(255,255,255))
                  .setColorBackground(color(20,20,20))
                  .setColorForeground(color(0,0,0))
                  .setText("Slope")
                  .hideScrollbar();
//Add Text Field for "Intercept"
  interceptTextarea = cp5.addTextarea("intercept")
                  .setPosition(10,380)
                  .setSize(55,25)
                  .setLineHeight(14)
                  .setColor(color(255,255,255))
                  .setColorBackground(color(20,20,20))
                  .setColorForeground(color(0,0,0))
                  .setText("Intercept")
                  .hideScrollbar();
//Add Text Field for aa
  aaTextarea = cp5.addTextfield("aa")
                  .setPosition(75,350)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelaa = aaTextarea.getCaptionLabel();
              labelaa.setText("");
                  
//Add Text Field for ab
  abTextarea = cp5.addTextfield("ab")
                  .setPosition(75,380)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
                  Label labelab = abTextarea.getCaptionLabel();
                  labelab.setText("");
                  
//Add Text Field for ba                 
                  baTextarea = cp5.addTextfield("ba")
                  .setPosition(160,350)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
               Label labelba = baTextarea.getCaptionLabel();
               labelba.setText("");
               
//Add Text Field for bb
   bbTextarea = cp5.addTextfield("bb")
                  .setPosition(160,380)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelbb = bbTextarea.getCaptionLabel();
              labelbb.setText("");
              
//Add Text Field for ca
   caTextarea = cp5.addTextfield("ca")
                  .setPosition(245,350)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelca = caTextarea.getCaptionLabel();
              labelca.setText("");
              
 //Add Text Field for cb
   cbTextarea = cp5.addTextfield("cb")
                  .setPosition(245,380)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelcb = cbTextarea.getCaptionLabel();
              labelcb.setText("");
              
                          //Add Text Field for da
   daTextarea = cp5.addTextfield("da")
                  .setPosition(330,350)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelda = daTextarea.getCaptionLabel();
              labelda.setText("");
              
                          //Add Text Field for db
   dbTextarea = cp5.addTextfield("db")
                  .setPosition(330,380)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labeldb = dbTextarea.getCaptionLabel();
              labeldb.setText("");
                  
                  //Add Text Field for ea
   eaTextarea = cp5.addTextfield("ea")
                  .setPosition(415,350)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelea = eaTextarea.getCaptionLabel();
              labelea.setText("");
                  
                  //Add Text Field for eb
   ebTextarea = cp5.addTextfield("eb")
                  .setPosition(415,380)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labeleb = ebTextarea.getCaptionLabel();
              labeleb.setText("");
              
                  //Add Text Field for fa
   faTextarea = cp5.addTextfield("fa")
                  .setPosition(500,350)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelfa = faTextarea.getCaptionLabel();
              labelfa.setText("");
              
                    //Add Text Field for fb
   fbTextarea = cp5.addTextfield("fb")
                  .setPosition(500,380)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelfb = fbTextarea.getCaptionLabel();
              labelfb.setText("");
                                      //Add Text Field for ga
   gaTextarea = cp5.addTextfield("ga")
                  .setPosition(585,350)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelga = gaTextarea.getCaptionLabel();
              labelga.setText("");
                  
                   //Add Text Field for gb
    gbTextarea = cp5.addTextfield("gb")
                  .setPosition(585,380)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelgb = gbTextarea.getCaptionLabel();
              labelgb.setText("");
                   //Add Text Field for ha
    haTextarea = cp5.addTextfield("ha")
                  .setPosition(670,350)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelha = haTextarea.getCaptionLabel();
              labelha.setText("");
                                     //Add Text Field for hb
    hbTextarea = cp5.addTextfield("hb")
                  .setPosition(670,380)
                  .setSize(75,25)
                  .setColor(color(20,20,20))
                  .setColorBackground(color(255,100))
                  .setColorForeground(color(0,0,0));
              Label labelhb = hbTextarea.getCaptionLabel();
              labelhb.setText("");

}

//If button "READ CONFIG" is pushed, send a "1" on the serial port to trigger Arduino to read
//the EEPROM and send values to Serial so we can parse them
void READ () {
myPort.write(60);
myPort.write(1);
myPort.write(62);
 }
 
//If button "SEND CONFIG" is pushed, send a "2" on the serial port to trigger
//the Arduino to read the serial bus and we'll write 16 values to Serial so the Arduino
//can write them to their assigned EEPROM addresses

 void SEND () {
myPort.write(60);
myPort.write(2);
 
//To send the contents of our text fields to Serial, we'll need to define some more strings
 String aasend = aaTextarea.getText();
 String absend = abTextarea.getText();
 String basend = baTextarea.getText();
 String bbsend = bbTextarea.getText();
 String casend = caTextarea.getText();
 String cbsend = cbTextarea.getText();
 String dasend = daTextarea.getText();
 String dbsend = dbTextarea.getText();
 String easend = eaTextarea.getText();
 String ebsend = ebTextarea.getText();
 String fasend = faTextarea.getText();
 String fbsend = fbTextarea.getText();
 String gasend = gaTextarea.getText();
 String gbsend = gbTextarea.getText();
 String hasend = haTextarea.getText();
 String hbsend = hbTextarea.getText();
 
//Now let's write our text extracted from our text fields to serial one at a time with a 
// new lin '\n' in between each 
 myPort.write(2);
 myPort.write(aasend);
 myPort.write('\n');
 myPort.write(absend);
 myPort.write('\n');
 myPort.write(basend);
 myPort.write('\n');
 myPort.write(bbsend);
 myPort.write('\n');
 myPort.write(casend);
 myPort.write('\n');
 myPort.write(cbsend);
 myPort.write('\n');
 myPort.write(dasend);
 myPort.write('\n');
 myPort.write(dbsend);
 myPort.write('\n');
 myPort.write(easend);
 myPort.write('\n');
 myPort.write(ebsend);
 myPort.write('\n');
 myPort.write(fasend);
 myPort.write('\n');
 myPort.write(fbsend);
 myPort.write('\n');
 myPort.write(gasend);
 myPort.write('\n');
 myPort.write(gbsend);
 myPort.write('\n');
 myPort.write(hasend);
 myPort.write('\n');
 myPort.write(hbsend);
 myPort.write(62);
 
//We can choose to also send Strings above to the Processing console for debugging purposes
 print(aasend);
 print('\n');
}

void draw(){
  while (myPort.available() > 0) {
    
//We'll create values in our Strings as we're reading them from Serial
    aaString = myPort.readStringUntil(nl);
    abString = myPort.readStringUntil(nl);
    baString = myPort.readStringUntil(nl);
    bbString = myPort.readStringUntil(nl);
    caString = myPort.readStringUntil(nl);
    cbString = myPort.readStringUntil(nl);
    daString = myPort.readStringUntil(nl);
    dbString = myPort.readStringUntil(nl);
    eaString = myPort.readStringUntil(nl);
    ebString = myPort.readStringUntil(nl);
    faString = myPort.readStringUntil(nl);
    fbString = myPort.readStringUntil(nl);
    gaString = myPort.readStringUntil(nl);
    gbString = myPort.readStringUntil(nl);
    haString = myPort.readStringUntil(nl);
    hbString = myPort.readStringUntil(nl);
    
//Now we'll assign values to our "trimmed" Strings with the following
    String aatrim = aaString.trim();
    String abtrim = abString.trim();
    String batrim = baString.trim();
    String bbtrim = bbString.trim();
    String catrim = caString.trim();
    String cbtrim = cbString.trim();
    String datrim = daString.trim();
    String dbtrim = dbString.trim();
    String eatrim = eaString.trim();
    String ebtrim = ebString.trim();
    String fatrim = faString.trim();
    String fbtrim = fbString.trim();
    String gatrim = gaString.trim();
    String gbtrim = gbString.trim();
    String hatrim = haString.trim();
    String hbtrim = hbString.trim();
//If we get a nibble... let's stuff those "trimmed" strings into each respective text field

    if (aaString != null) {
      
      background(color(20,20,20));
      
//We'll use our trimmed Strings to properly display values in the text fields with no
//leading or trailing spaces, newlines, etc.
   aaTextarea.setText (aatrim);
   abTextarea.setText (abtrim);
   baTextarea.setText (batrim);
   bbTextarea.setText (bbtrim);
   caTextarea.setText (catrim);
   cbTextarea.setText (cbtrim);
   daTextarea.setText (datrim);
   dbTextarea.setText (dbtrim);
   eaTextarea.setText (eatrim);
   ebTextarea.setText (ebtrim);
   faTextarea.setText (fatrim);
   fbTextarea.setText (fbtrim);
   gaTextarea.setText (gatrim);
   gbTextarea.setText (gbtrim);
   haTextarea.setText (hatrim);
   hbTextarea.setText (hbtrim);
                                  }}}

I don’t have much experience with Arduino nor do I own one now, but one thing you can do to improve code readability is to use array or dict and loop through them with for loop, because I see many repetitions.

and can you explain where you get null pointer? that way, someone may have a suggestion without having to set up the whole Arduino board themselves.

@jshackel8 Hi, I’ve just run your Processing sketch (as @ErraticGenerator says you must read-up and use arrays, lots of lines of code will be avoided), not yet with the sketch in the Arduino, but I have this error:

[0] "COM3"
[1] "COM6"
COM6
Jan 09, 2021 5:50:23 PM controlP5.ControlBroadcaster printMethodError
SEVERE: An error occured while forwarding a Controller event, please check your code at SEND
java.lang.reflect.InvocationTargetException

Is that the error you are seeing?

Hi @jshackel8, The problem is that SEND() is being called when the button is created. Then SEND() tries to aaTextarea.getText(); before aaTextarea has been created. You can verify this by adding a few print statements through setup and one in SEND().

You can avoid the problem by moving the creation of the buttons to after the creation of the text areas. What I don’t understand is why creating the buttons is running their action code. It shouldn’t run until they are clicked. That needs investigating in a small program with just 1 button and 1 action routine. Sadly I can’t do any more today.

1 Like

I’ve just tried the example ControlP5button and that does it. The button action is called when the button is created. Am I missing something? I don’t know how to fix properly, but you can defend against it with a boolean to show when the buttons are ready.

import controlP5.*;
ControlP5 cp5;
boolean buttonsReady = false;

void setup() 
{
  size(400, 600);
  cp5 = new ControlP5(this);

  cp5.addButton("Button")
    .setPosition(10, 10)
    .setSize(100, 20)
    .setValue(0)
    ;

  buttonsReady = true;
}

void draw() {}

public void Button() 
{ 
  if (buttonsReady) 
  {
    println("Button Event");
  }
}