328P Need to clean up my sketch and write the code correctly

I'd really like to clean up my code to have classes and functions instead of everything going in the loop. Mostly I just google hack my codes to work, but I want this particular code to just be finished.

Another user in one of my threads mentioned classes, so that is something I need to look at. Also, I would love to be able to figure out how to do a self calibration during the setup, and possibly add a calibration by pressing a button, which resets data right now, for 5 seconds (I understand from my google search the code for the button press will essentially be a debounce, but the function it calls I need help with).

The code itself works, but I added a precision voltage reference (LM4132A) to the project, and oddly enough the raw readings from the external adc are not as stable, ie, they change from power up to power up. When I just use the voltage regulator (L7805cv) in the circuit for the reference, it is more stable. I can then do a manual calibration and set the offsets when I first build the unit and it is fine. Now it seems I need to add the ability to "calibrate", which is just editing the offset values.

I would also like to make functions and clean up my main loop a bit.

The hardware is pretty simple (so is the code I'm told, lol). The device is powered by 7.0V-15Vdc, there is a precision voltage ref that connects to an external 12 bit adc. There are 3 linear hall effect sensors connecting to the external adc via a voltage divider to drop their output down so the high value is 4.096V or less. Based on the reference. The voltage divider is a 10kΩ/42kΩ divider. There is a button on A2 to reset the data.

The programming oversamples the external adc by 2 bits, then averages it 16x (at least that is what I think I'm doing, lol). I need the resolution because the sensors have a 0.0005V sensitivity and I want to be able to see increments of 1 step.

And, here is the code...

/* Rotor Master v2.2
A WHM Racing product
written by Andrew Sarratore
Date: 7/31/2023

v1.2
added logo to the setup and loop
Date: 9/10/2023

v1.3
Changed from single read to an average of 30
Date: 9/17/2023

v1.4
Added code for oversampling the mcp3204 to 14bits and change average to 16x
Date: 9/28/2023 
*/



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

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define SELPIN 10 //Selection Pin
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//Clock
#define RST 16// Reset Pin for Data



// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Variables for Oversampling
unsigned long OADC1=0;
unsigned long OADC2=0;
unsigned long OADC3=0;
unsigned long Oavg1=0;
unsigned long Oavg2=0;
unsigned long Oavg3=0;
unsigned long OverADC1;
unsigned long OverADC2;
unsigned long OverADC3;
int l=0;
int m=0;
int n=0;
// End variables for Oversampling



// Variables to edit
double VCC = 4.097; // Output Voltage of reference 
float QOV1 = 1.990;  // Quiescent Output Sensor1
float QOV2 = 1.986;  // Quiescent Output Sensor2
float QOV3 = 1.986;  // Quiescent Output Sensor3
float M1 = 1.349; // Multiplier Sen1
int Offset1 = 7958; // Set raw reading to 0
int Offset2 = 7942; // Set raw reading to 0
int Offset3 = 7942; // Set raw reading to 0
float Sensitivity = 0.0005;
int DEL=0;
// End variable to edit



float divider = (16384 / VCC ); // Compensate for Voltage difference
int readvalue1; //Raw read from ADC1
int readvalue2; //Raw read from ADC2
int readvalue3; //Raw read from ADC3
int readADC1; //Raw read from ADC1
int readADC2; //Raw read from ADC2
int readADC3; //Raw read from ADC3
int Zero1; // Zero the reading for calculations, allows for +/-
int Zero2; // Zero the reading for calculations, allows for +/-
int Zero3; // Zero the reading for calculations, allows for +/-
int Gauss1; //Calculated Gauss
int Gauss2; //Calculated Gauss
int Gauss3; //Calculated Gauss
int HighGauss1=0; //Variable for Max + Value
int HighGauss2=0; //Variable for Max + Value
int HighGauss3=0; //Variable for Max + Value
int LowGauss1=0; //Variable for Max - Value
int LowGauss2=0; //Variable for Max - Value
int LowGauss3=0; //Variable for Max - Value
double Voltage1; // Voltage of Zero
float Voltage2; // Voltage of Zero
float Voltage3; // Voltage of Zero
float G1; // Gauss before Multiplier
float G2; // Gauss before Multiplier
float G3; // Gauss before Multiplier
float OffsetV1;
float OffsetV2;
float OffsetV3;
int i = 0;
int j = 0;
int k = 0;
long int avg1 = 0;
long int avg2 = 0;
long int avg3 = 0;
long int ADC1 = 0;
long int ADC2 = 0;
long int ADC3 = 0;
long int AverageADC1 = 0;
long int AverageADC2 = 0;
long int AverageADC3 = 0;
int RESET=1023;
//Bitmap Logos

const unsigned char LogoIcon[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x23, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x23, 0x60, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x30, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xfe, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x40, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x78, 0x0f, 0x00, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xe0, 0x07, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x07, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x07, 0xff, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x07, 0xff, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x03, 0xff, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x03, 0xff, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x03, 0xff, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x03, 0xff, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x07, 0xff, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc3, 0xe0, 0x07, 0xe3, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x03, 0xf0, 0x07, 0xe0, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0xe0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x0f, 0xe0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x0f, 0xf0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x1f, 0xf0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x7f, 0xf0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

const unsigned char Logotxt [] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x0b, 0x40, 0x1d, 0xc0, 0x3b, 0x00, 0x00, 0x7c, 0x00, 0x70, 0x01, 0xc0, 0x38, 0x07, 0x60, 0x07,
  0x0b, 0xc0, 0x0d, 0x80, 0x1b, 0x00, 0x00, 0x3c, 0x00, 0x70, 0x03, 0x80, 0x18, 0x03, 0x60, 0x0f,
  0x0f, 0xc0, 0x1f, 0x80, 0x1f, 0x00, 0x00, 0x2c, 0x00, 0xf0, 0x02, 0x00, 0x10, 0x03, 0xc0, 0x0f,
  0x6f, 0x80, 0xff, 0x81, 0xfe, 0x00, 0x03, 0xbc, 0x0f, 0xf0, 0x3e, 0x01, 0xf0, 0x3b, 0xc0, 0x6b,
  0x6f, 0x80, 0xff, 0x80, 0xd6, 0x00, 0x01, 0xe8, 0x07, 0xf0, 0x1f, 0x80, 0xf0, 0x1a, 0xc0, 0x6f,
  0x0f, 0x80, 0x15, 0x80, 0x76, 0x00, 0x00, 0xec, 0x03, 0xb0, 0x07, 0x80, 0x70, 0x0e, 0xc0, 0x0e,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};



void setup() {
  Serial.begin(9600);
   if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    }
  delay(1000);
  display.clearDisplay();
  display.drawBitmap(0, 0, LogoIcon, 128, 64, WHITE);
  display.display();
  pinMode(SELPIN, OUTPUT);
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK, OUTPUT);
  pinMode(RST, INPUT_PULLUP);
  digitalWrite(SELPIN,HIGH);
  digitalWrite(DATAOUT,LOW);
  digitalWrite(SPICLOCK,LOW);
  delay(500);

}


int read_adc(int channel){
  int adcvalue = 0;
  byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)

  //allow channel selection
  commandbits|=((channel-1)<<3);

  digitalWrite(SELPIN,LOW); //Select adc
  // setup bits to be written
  for (int q=7; q>=3; q--){
    digitalWrite(DATAOUT,commandbits&1<<q);
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);    
  }

  digitalWrite(SPICLOCK,HIGH);    //ignores 2 null bits
  digitalWrite(SPICLOCK,LOW);
  digitalWrite(SPICLOCK,HIGH);  
  digitalWrite(SPICLOCK,LOW);

  //read bits from adc
  for (int q=11; q>=0; q--){
    adcvalue+=digitalRead(DATAIN)<<q;
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);
  }
  digitalWrite(SELPIN, HIGH); //turn off device
  return adcvalue;
}


void loop() {
int RESET=analogRead(A2);
if (RESET<100) {
 Gauss1=0;
 Gauss2=0;
 Gauss3=0;
 HighGauss1=0;
 LowGauss1=0;
 HighGauss2=0;
 LowGauss2=0;
 HighGauss3=0;
 LowGauss3=0; 
}
  


// Oversample ADC1 by 2 bit
while(l<16) {
  OADC1 = read_adc(1);
  Oavg1 += OADC1;
  l++;
}
OverADC1 = Oavg1>>2;
Oavg1=0;
l=0;

// Average the Oversample 16x
while(i<30) {
  ADC1 = OverADC1;
  avg1 += ADC1;
  i++;
}
AverageADC1 = avg1/30;
avg1=0;
i=0;


// Oversample ADC2 by 2 bit
while(m<16) {
  OADC2 = read_adc(2);
  Oavg2 += OADC2;
  m++;
}
OverADC2 = Oavg2>>2;
Oavg2=0;
m=0;

// Average the Oversample 16x
while(j<30) {
  ADC2 = OverADC2;
  avg2 += ADC2;
  j++;
}
AverageADC2 = avg2/30;
avg2=0;
j=0;

// Oversampel ADC3 by 2 bit
while(n<16) {
  OADC3 = read_adc(3);
  Oavg3 += OADC3;
  n++;
}
OverADC3 = Oavg3>>2;
Oavg3=0;
n=0;

// Average the Oversample 16x
while(k<30) {
  ADC3 = OverADC3;
  avg3 += ADC3;
  k++;
}
AverageADC3 = avg3/30;
avg3=0;
k=0;









OffsetV1 = (Offset1 - (QOV1 * divider)) / divider;
OffsetV2 = (Offset2 - (QOV2 * divider)) / divider;
OffsetV3 = (Offset3 - (QOV3 * divider)) / divider;
Voltage1 = (AverageADC1) / divider;
Voltage2 = (AverageADC2) / divider;
Voltage3 = (AverageADC3) / divider;
Zero1 = AverageADC1 - Offset1;
Zero2 = AverageADC2 - Offset2;
Zero3 = AverageADC3 - Offset3;
G1 = ((Voltage1 - OffsetV1)-QOV1) / Sensitivity;
G2 = ((Voltage2 - OffsetV2)-QOV2) / Sensitivity;
G3 = ((Voltage3 - OffsetV3)-QOV3) / Sensitivity;
Gauss1 = G1 * M1;
Gauss2 = G2 * M1;
Gauss3 = G3 * M1;
if (Gauss1 > HighGauss1) HighGauss1 = Gauss1;
if (Gauss2 > HighGauss2) HighGauss2 = Gauss2;
if (Gauss3 > HighGauss3) HighGauss3 = Gauss3;
if (Gauss1 < LowGauss1) LowGauss1 = Gauss1;
if (Gauss2 < LowGauss2) LowGauss2 = Gauss2;
if (Gauss3 < LowGauss3) LowGauss3 = Gauss3;


  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.drawBitmap(0, 0, Logotxt, 128, 15, WHITE);
  display.setTextSize(2);
  display.setCursor(0,16);
  if ((Gauss1 <= 10) && (Gauss1 >= -10)) {
    display.println("0");
  }
    else
    {
      display.print(Gauss1);
    }

  display.setCursor(64,16);
  if (Gauss1 >= 0)
   {
     display.print("+");
     display.print(HighGauss1);
   }
     else
     {
       display.print(LowGauss1);
     }

  display.setCursor(0,32);
  if ((Gauss2 <= 10) && (Gauss2 >= -10)) {
  display.println("0");
  }
    else
    {
      display.print(Gauss2);
    }

  display.setCursor(64,32);
  if (Gauss2 >= 0)
    {
      display.print("+");
      display.print(HighGauss2);
    }
     else
     {
       display.print(LowGauss2);
     }

  display.setCursor(0,48);
  if ((Gauss3 <= 10) && (Gauss3 >= -10)) {
    display.println("0");
  }
    else
    {
      display.print(Gauss3);
    }

  display.setCursor(64,48);
  if (Gauss3 >= 0)
    {
      display.print("+");
      display.print(HighGauss3);
    }
      else
      {
        display.print(LowGauss3);
      }

  display.display();
 
 
 
 Serial.print(AverageADC1);
 Serial.print(" RV1 ");
 Serial.println();
 Serial.print(AverageADC2);
 Serial.print(" RV2 ");
 Serial.println(" ");
 Serial.print(AverageADC3);
 Serial.print(" RV3 ");
 Serial.println(" ");
 
 

delay(DEL);

 
}



So, you want someone to rewrite your code properly?

Does it work well as it is?

No, I don't want someone to rewrite it. I want to rewrite it properly. I just don't know where to start. I have started a C++ course, but there is a lot in that, lol.

The code works, but I want to add the ability to "calibrate" the sensors, and I have no idea where to start with that. I added a quick adjustment in the setup, but I would like to use a function to calibrate the offset.

I do want to be able to do this myself, just need the right direction. And the arduino doing many things at once sketch hasn't helped...

I don't even know how to answer this question. You are the one who said I needed a class in my other thread. Do you have to have a separate .h file or library for the class, I don't think you do, but google results kind of say you do. I'm pretty sure in one of my other projects with a tft display, the tutorial I watched had a guy create a class in the sketch for buttons and didn't create another file.

How do I determine what can go in a class?

But regardless of all of that... Can I put all my adc reads and oversampling/averaging into functions and not mess up the results? Also, I don't know where to start with a calibration routine.

You can start with this: Programming With Classes and Objects on the Arduino - Circuit Basics

That's funny, I'm already watching that one, lol.

The problem is all these videos are too abstract. They may apply, but they don't apply specifically enough for me to grasp the concepts. I need someone to interact it to understand this a bit better. How do I go about finding a person to actually interact with, and not just typing on a forum?

I tutor on wyzant and other sites. I don't tutor class design in C++, other language though. Expect it to be expensive for one-on-one training. Or take a class at a local college.

Or you can just take a shot and ask for help after you've done proper research and made a good attempt.

Out of curiosity, what is expensive? I've been contemplating getting another degree, but that is a big time/money investment for a side hustle/hobby, lol.

I charge $49/hr for my standard rate, but it goes as high as $165/hr for some more select skills that I teach.

don't necessarily need classes, but use a struct to capture the variables for what looks like 3 sets of data a to break loop() into sub-functions to make the code more maintainable and smaller

That sounds good, lol. So where do I start with that?

Another question, I was just looking at difference of while vs for. I didn’t realize that they were loops, I thought they only looped because you put it in the main loop. So while and for loops are blocking. However that makes it easier to do a calibration. I was trying to figure out how to do an average in the setup, but a while loop should work there just like it does in the loop? Is this correct?

Classes is a great idea. Especially when your doing multiple things exactly the same. For example start with your adc readings then you can expand to your other readings. Also its a great learning experience and cleans your code.

If it where my project i would also make a display class where all the display stuff is kept contained.

One of the things with classes where it gets trickey is dependencys. Your display for example will probably need to output some of the adc readings. That can be dealt with later, for now just keep the readings as public variables so they can be accessed easily.

A class first needs a header file. This defines what methods are in the class and what variables can bw accessed outside the class. We also set methods as public or private. So the header doesnt get included multiple times in the file we need to do an #ifndef

Lets call your class HallEffect (call it what you wish) the hall effect class is going to also require a channel number. Now we can pass that channel number in the class constructer. However a good practise is to hahe an Init function, or a begin function. The reason being, when the class is created, some of the arduino methods (eg serial.begin) have not been called. You wont be able to do any serial printing in your constructor.

This is all type on phone so syntex called be wrong
So create a new tab called HallEffect.h
In that file

#ifndef HallEffect_H
#define HallEffect_H

class HallEffect
{
public:

  int16_t readValue;
  Int16_t readADC;


  void Begin(uint8_t channel);
  Void Update();
};

#endif

Now create a file called HallEffect.cpp

#include "HallEffect.h"

void HallEffect::Begin(uint8_t channel)
{
  this->channel = channel;
}

void HallEffect::Update()
{
  //insert your reading adc code here. Channel your reading is the variable channel - we saved this variable in your header file so you can access it directly
}

Now in your main ino file you will need to have an #include "HallEffect.h"

You will also need to create instances of this class in your ino file. Because theres 3 of them an array would be perfect

HallEffect hallEffectList[3];

In your setup method we need to set them up with your channel numbers. We can do it like this if they are not sequential

hallEffectList[0].init(1);
hallEffectList[1].init(5);

Or if they are sequential, we can simply do a for loop

For (int8_t i = 0; i <3; i++)
{
  hallEffectList[i].Init(i);
}

Now in our loop we can update them

For (int8_t i = 0; i <3; i++)
{
  hallEffectList[i].Update();
}

If we need to access a variable from our class we can go

int16_t letsAccess = hallEffectList[0].readADC;

This is typed on phone but should be a basic outline of what you need to do. You can add other methods etc or whatever you need.

Maybe this is the answer you're looking for.  You don't need a header file if the class is defined within the sketch.

Witness:

/* basic class tutorial

    http://www.cplusplus.com/doc/tutorial/classes/

*/

class Rectangle {
  int width, height;  // These variables are private by default

public:
  char place;
  void set_values(int, int);
  int area() {  // Rectangle member function, aka method
    return width * height;
  }
}; // end of class definition

Rectangle rect;  // Instantiate an object of the Rectangle class

void Rectangle::set_values(int x, int y) {
  width = x;
  height = y;
}

void setup() {
  Serial.begin(115200);
  rect.set_values(7, 6);  // Give object the parameter values
                          // ie. call member function
  Serial.print("area: ");
  Serial.println(rect.area());  // Call Rectangle member function
                                // which computes the area
}

void loop() {
}

You could do Rectangle rect17 or, Rectangle quadrilateral29 to create new objects.   Of course you then have to refer to such as rect17.set_values(31,11); , etc.

Refer to the link within the sketch for a more blow-by-blow account.

1 Like

take a look at chap 6 in The C Programming Language on structures and tell me if it make sense

your our code appears to have 3 sets of variables, all the variables with 1,2 or 3 suffixes.

one approach is to use arrays to make the code more manageable. blocks of code such as the following could be captured in a sub-function with an array index parameter to operate on one of the 3 sets of variables, as well as any processing parameters for those specific variables (e.g. # of oversamples)

    // Oversampel ADC3 by 2 bit
    while(n<16) {
        OADC3 = read_adc(3);
        Oavg3 += OADC3;
        n++;
    }
    OverADC3 = Oavg3>>2;
    Oavg3=0;
    n=0;

    // Average the Oversample 16x
    while(k<30) {
        ADC3 = OverADC3;
        avg3 += ADC3;
        k++;
    }
    AverageADC3 = avg3/30;
    avg3=0;
    k=0;

while arrays consolidate the # of instances of that variable, a struct (or class) captures all the variables in a particular set and there can be an array of structs.

and similary, those same sub-functions used to operate on the arrays can be used to operate on the variables of a particular struct, either using an array index or pointer to the struct.

the goal is to consolidate the variables and functions operating on the variables and to avoid writing redundant code

1 Like

press CTRL-T in your IDE and format the code.

Then check each variable if it has the correct size ... there are so many global int so I assume lot of them don't need to be signed types (your raw readings from an ADC will never get signed).

Are some of the variables constants? Mark them constant.

When you are reworking your variables already group them in a locigal order, what belongs together, what has an relation to other variables.

You have variables named x1, x2, x3 ... bad idea. Read about arrays.

You have several variables with the same numbering x1, and y1. Do they belong together? Make a structure with the members x and y and make an array of that structure if you need several instances of it.

Use functions for code which is similar ... everything you have "programmed" with "CTRL-C CTRL-V" and has duplicates in code is a potential function.

Clean up your code before you start making classes from your structures.

Post your next program version, which should have less than 75% of lines of code without loosing any functionality. Less code -> less possibility to make errors.

3 Likes

This

// Average the Oversample 16x
while(i<30) {
  ADC1 = OverADC1;
  avg1 += ADC1;
  i++;
}
AverageADC1 = avg1/30;
avg1=0;
i=0;

seems wasteful. It is not improving anything by averaging, as you do not take new readings.

a7

2 Likes

That first part is supposed to be commented out. That is old code. I thought it was commented out.

EDIT: I'm going to have to go back and look at my sketch. It is supposed to be an oversample by 2 bits, and then average the oversample.

Classes are powerful and useful. For a class to provide real benefits though, you'll need functions. I'd start with using those instead and only refactor into classes once you have use of functions nailed.

The most basic thing a function can do is to take some code and move it out of another function while giving the snippet extracted a name.

You have a section in loop that has a bunch of serial printing in it. You could change it to:

void doSerialPrinting()
{
 Serial.print(AverageADC1);
 Serial.print(" RV1 ");
 Serial.println();
 Serial.print(AverageADC2);
 Serial.print(" RV2 ");
 Serial.println(" ");
 Serial.print(AverageADC3);
 Serial.print(" RV3 ");
 Serial.println(" ");
}

And call this from loop instead of having all those prints making loop longer. As a bonus, using good names self documents your code.

There are several similar standalone sections that can run in their own functions, making look shorter and cleaner. Come back when that's done and then function parameters can help with repetitive code. IMHO, jumping right to classes at this point is several bridges too far.

5 Likes