/*
.........................................................................................
................... based and inspired on a video by Stefan Pynappels ...................
...................
https://www.youtube.com/watch?v=FW8ivDylOr8 .........................
.........................................................................................
Measuring principle - gravity with 3 axis accelerometer ADXL345
For further information
http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf
http://www.analog.com/media/en/technical-documentation/application-notes/AN-1057.pdf
Hardware: ADXL 345, LCD 1602 with I2C interface, ARDUINO pro mini
Wiring: ADXL 345 and LCD 1602 with I2C -> Arduino SDA and SCL, buttons to
Arduino Button D2, D3, D4 and D6, Jumper to D5
D2 - zero setting
D3, D4 - up and down depth value
D5 - throw or secant measurement
D6 - write depth to eeprom
See
https://www.arduino.cc/en/tutorial/button for wiring circuit
Added chord depth save to eeprom! LED on 13 BLINK 500ms
*/
/*******************************************************************************************/
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <ADXL345.h>
#include <EEPROM.h>
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7); // PCF8754 - 0x27, PCF8754A - 0x3F !
ADXL345 adxl; // variable adxl is an instance of the ADXL345 library
/************************************ DEFINED VARIABLES ************************************/
int count; // chord depth [mm]
int countnew;
int x, y, z; // raw values from sensor (-255 ... 0 ... +255)
int angle;
int arrow; // 1 -> up, 2 -> down
int relative; // for zeroing
float rad;
float xg, yg, zg; // g values
float calc;
float tilt;
float tiltfiltered;
float value01 = 0.0;
float value02 = 0.0;
int led = 13; // signal eeprom write
/************************************ SENSOR CALIBRATION ***********************************/
/*
#define offsetX -7.0 // OFFSET values SENSOR #1 CALIBRATION
#define offsetY 4.0 // replace "0" with calculated value after sensor calibration
#define offsetZ -20.0
#define gainX 1.051 // GAIN factors
#define gainY 1.074 // replace "1" with calculated value after sensor calibration
#define gainZ 0.976
*/
#define offsetX -4.5 // OFFSET values SENSOR #2 CALIBRATION
#define offsetY 0.5 // replace "0" with calculated value after sensor calibration
#define offsetZ -27.5
#define gainX 1.049 // GAIN factors
#define gainY 1.065 // replace "1" with calculated value after sensor calibration
#define gainZ 0.990
/************************************ Graphics for display **********************************/
uint8_t degree[8] = {140, 146, 146, 140, 128, 128, 128, 128}; // °
uint8_t arrowup[8] = {132, 142, 132, 132, 132, 128, 128, 128}; // Arrow up
uint8_t arrowdown[8] = {128, 128, 128, 132, 132, 132, 142, 132,}; // Arrow down
uint8_t arrowleft[8] = {128, 128, 136, 159, 136, 128, 128, 128,}; // Arrow left
// 128 is empty line, then add 16,8,4,2,1 to fill pixel. example 00x00 > 132, 0x0x0 > 138
/*******************************************************************************************/
void setup() {
lcd.begin (16, 2); // for 16 x 2 LCD module
lcd.setBacklightPin(3, POSITIVE);
lcd.setBacklight(HIGH);
lcd.createChar(0, degree);
lcd.createChar(1, arrowup);
lcd.createChar(2, arrowdown);
lcd.createChar(3, arrowleft);
adxl.powerOn();
/*******************************************************************************************/
// START SCREEN
/*******************************************************************************************/
lcd.home ();
lcd.print("RC - METER");
lcd.setCursor (0, 1);
lcd.print("ANGLE AND THROW");
delay(3000);
lcd.clear ();
lcd.print("RC - METER");
lcd.setCursor (0, 1);
lcd.print(" >> OR <<");
delay(3000);
lcd.clear ();
lcd.print("RC - METER");
lcd.setCursor (0, 1);
lcd.print("ANGLE AND SECANT");
delay(3000);
lcd.clear ();
lcd.print("ZERO SET");
lcd.setCursor (0, 1);
lcd.write(byte(2));
delay(2000);
lcd.clear ();
lcd.print("CORD depth[mm]");
lcd.setCursor (5, 1);
lcd.write(byte(1)); lcd.setCursor (7, 1); lcd.write(byte(2));
delay(2000);
lcd.clear ();
lcd.print("CORD to eeprom");
lcd.setCursor (0, 1);
lcd.write(byte(3)); lcd.write(byte(3)); lcd.print(" ....to save!");
delay(2000);
/*******************************************************************************************/
count = EEPROM.read(0); // read previous cord depth from eeprom
countnew = count;
}
/*******************************************************************************************/
void loop() {
if (digitalRead(2) == HIGH) { // zero setting
relative = angle;
}
if (digitalRead(6) == HIGH) { // chord depth -> eeprom
eepromsave ();
}
while (digitalRead(3) == HIGH) { // increase chord depth
increase ();
}
while (digitalRead(4) == HIGH && countnew > 1) { // decrease chord depth
decrease ();
}
adxl.readAccel(&x, &y, &z); // read the accelerometer values and store them in variables
xg = 0.00385 * (x - offsetX) / gainX; // 0.00385 to convert the raw data to Gs
yg = 0.00385 * (y - offsetY) / gainY; // offset and gain for calibration
zg = 0.00385 * (z - offsetZ) / gainZ;
calc = xg / sqrt ((sq(yg) + sq(zg))); //sensor orientation!
tilt = atan(calc) * 57.296;
tiltfiltered = tilt * 0.5 + value01 * 0.3 + value02 * 0.2; // see
http://forum.arduino.cc/index.php?topic=184067.0
value02 = value01;
value01 = tiltfiltered;
angle = int(tiltfiltered) * -1; //sensor orientation!
lcd.setCursor (0, 0); // go to start of 1st line
lcd.clear();
if ((angle - relative) > 0) {
arrow = 1; //arrow ↑↑↑
}
else {
arrow = 2; //arrow ↓↓↓
}
/*******************************************************************************************/
if ((angle - relative) == 0) {
lcd.print("ANGLE:"); lcd.print(abs(angle - relative)); lcd.write(byte(0));
}
else {
lcd.print("ANGLE:"); lcd.print(abs(angle - relative)); lcd.write(byte(0));
lcd.write(byte(arrow));
}
lcd.setCursor (0, 1);
rad = abs(angle - relative) * 0.017453;
// read the state of the jumper value:
if (digitalRead(5) == HIGH) {
lcd.print("SECANT:"); lcd.print(int(2 * countnew * sin(rad / 2))); lcd.print("mm");
lcd.print(" ("); lcd.print(countnew); lcd.print(")");
}
else {
lcd.print("THROW:"); lcd.print(int(countnew * sin(rad))); lcd.print("mm"); lcd.print(" (");
lcd.print(countnew); lcd.print(")");
}
delay(300);
}
/*******************************************************************************************/
void increase () {
countnew = countnew + 1;
lcd.setCursor (0, 1);
lcd.print("CORD depth:"); lcd.print(countnew); lcd.print("mm");
delay(250);
}
void decrease () {
countnew = countnew - 1;
lcd.setCursor (0, 1);
lcd.print("CORD depth:"); lcd.print(countnew); lcd.print("mm");
delay(250);
}
void eepromsave () {
if (count != countnew) {
count = countnew; // reset value chord depth
EEPROM.write(0, count);
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(500);
digitalWrite(led, LOW); // turn the LED on (HIGH is the voltage level)
}
}