Skip to content

Instantly share code, notes, and snippets.

@IOT-123
Last active January 7, 2018 23:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IOT-123/b8c70fadd7fb2691908190a6ee1bf5dd to your computer and use it in GitHub Desktop.
Save IOT-123/b8c70fadd7fb2691908190a6ee1bf5dd to your computer and use it in GitHub Desktop.
/*
* modified from code
* by Mathias Leroy
*
* V0.2 MODIFICATIONS
** I2C SET GET
** EEPROM SET GET
** REMOVE SERIAL OUTPUT - AFFECTED I2C
** ENABLE/DISABLE TRACKING
** MOVE SERVOS TO LIMITS VIA I2C
** READ CURRENT AVG INTENSITY VIA I2C
*/
#include <Wire.h>
#include <stdio.h>
#include <Servo.h>
#include <EEPROM.h>
#define EEPROM_VERSION 0
#define I2C_MSG_IN_SIZE 3
#define PIN_LDR_TL A0
#define PIN_LDR_TR A1
#define PIN_LDR_BR A3
#define PIN_LDR_BL A2
#define CMD_IDX_HORI 0 // future functions
#define CMD_IDX_VERT 1
#define CMD_VAL_MIN 0
#define CMD_VAL_MAX 1
#define IDX_I2C_ADDR 0
#define IDX_V_ANGLE_INIT 1
#define IDX_V_ANGLE_MIN 2
#define IDX_V_ANGLE_MAX 3
#define IDX_V_SENSITIVITY 4
#define IDX_V_STEP 5
#define IDX_H_ANGLE_INIT 6
#define IDX_H_ANGLE_MIN 7
#define IDX_H_ANGLE_MAX 8
#define IDX_H_SENSITIVITY 9
#define IDX_H_STEP 10
#define IDX_WAKE_SECONDS 11
#define IDX_SLEEP_MINUTES 12
#define IDX_V_DAWN_ANGLE 13
#define IDX_H_DAWN_ANGLE 14
#define IDX_DAWN_INTENSITY 15 // average of all LDRS
#define IDX_DUSK_INTENSITY 16 // average of all LDRS
#define IDX_END_EEPROM_SET 17
#define IDX_VOLTAGE 18
#define IDX_TRACKER_ENABLED 19
#define IDX_CURRENT_INTENSITY 20 // average of all LDRS - used for calculating IDX_DAWN_INTENSITY ambiant non-direct light
#define IDX_END_VALUES_GET 21
#define IDX_SIGN_1 22
#define IDX_SIGN_2 23
#define IDX_SIGN_3 24
Servo _servoH;
Servo _servoV;
byte _i2cVals[25] = {10, 90, 30, 150, 100, 5, 90, 0, 180, 100, 5, 30, 30, 40, 10, 30, 40, 0, 0, 1, 0, 0, 0, 0, 0};
int _servoLoopDelay = 10;
int _slowingDelay=0;
int _angleH = 0; // set in setup from EEPROM
int _angleV = 0; // set in setup from EEPROM
int _averageTop = 0;
int _averageRight = 0;
int _averageBottom = 0;
int _averageLeft = 0;
byte _i2cResponse = 0;
void setup()
{
getFromEeprom();
_angleH = _i2cVals[IDX_H_ANGLE_INIT];
_angleV = _i2cVals[IDX_V_ANGLE_INIT];
Wire.begin(_i2cVals[IDX_I2C_ADDR]);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
_servoH.attach(5);
_servoH.write(_i2cVals[IDX_H_ANGLE_INIT]);
_servoV.attach(11);
_servoV.write(_i2cVals[IDX_V_ANGLE_INIT]);
}
void loop()
{
getLightValues();
moveServos();
}
void getFromEeprom(){
if(
EEPROM.read(IDX_SIGN_1) != 'S' ||
EEPROM.read(IDX_SIGN_2) != 'T' ||
EEPROM.read(IDX_SIGN_3) != EEPROM_VERSION
) EEPROM_write_default_configuration();
EEPROM_read_configuration();
}
void EEPROM_write_default_configuration(){
for (int i = 0; i < IDX_END_EEPROM_SET; i++){
EEPROM.update(i, _i2cVals[i]);
}
EEPROM.update(IDX_SIGN_1,'S');
EEPROM.update(IDX_SIGN_2, 'T');
EEPROM.update(IDX_SIGN_3, EEPROM_VERSION);
}
void EEPROM_read_configuration(){
for (int i = 0; i < IDX_END_EEPROM_SET; i++){
_i2cVals[i] = EEPROM.read(i);
}
}
void receiveEvent(int count) {
if (count == I2C_MSG_IN_SIZE)
{
char cmd = Wire.read();
byte index = Wire.read();
byte value = Wire.read();
switch (cmd) {
case 'E':
_i2cVals[IDX_TRACKER_ENABLED] = 1;
break;
case 'D':
_i2cVals[IDX_TRACKER_ENABLED] = 0;
break;
// case 'M': // future functions
// moveServoToLimit(index, value);
// break;
case 'G':
if (index < IDX_END_VALUES_GET){
_i2cResponse = _i2cVals[index];
}
break;
case 'S':
if (index < IDX_END_EEPROM_SET){
_i2cVals[index] = value;
EEPROM.update(index, _i2cVals[index]);
}
break;
default:
return;
}
}
}
void requestEvent()
{
Wire.write(_i2cResponse);
}
void getLightValues(){
int valueTopLeft = analogRead(PIN_LDR_TL);
int valueTopRight = analogRead(PIN_LDR_TR);
int valueBottomRight = analogRead(PIN_LDR_BR);
int valueBottomLeft = analogRead(PIN_LDR_BL);
_averageTop = ( valueTopLeft + valueTopRight ) / 2;
_averageRight = ( valueTopRight + valueBottomRight ) / 2;
_averageBottom = ( valueBottomRight + valueBottomLeft ) / 2;
_averageLeft = ( valueBottomLeft + valueTopLeft ) / 2;
int avgIntensity = (valueTopLeft + valueTopRight + valueBottomRight + valueBottomLeft) / 4;
_i2cVals[IDX_CURRENT_INTENSITY] = map(avgIntensity, 0, 1024, 0, 255);
}
void moveServos(){
if (_i2cVals[IDX_TRACKER_ENABLED] == 0) return;
if ( (_averageLeft-_averageRight)>_i2cVals[IDX_H_SENSITIVITY] && (_angleH-_i2cVals[IDX_H_STEP])>_i2cVals[IDX_H_ANGLE_MIN] ) {
// going left
delay(_slowingDelay);
for (int i=0; i < _i2cVals[IDX_H_STEP]; i++){
_servoH.write(_angleH--);
delay(_servoLoopDelay);
}
}
else if ( (_averageRight-_averageLeft)>_i2cVals[IDX_H_SENSITIVITY] && (_angleH+_i2cVals[IDX_H_STEP])<_i2cVals[IDX_H_ANGLE_MAX] ) {
// going right
delay(_slowingDelay);
for (int i=0; i < _i2cVals[IDX_H_STEP]; i++){
_servoH.write(_angleH++);
delay(_servoLoopDelay);
}
}
else {
// doing nothing
delay(_slowingDelay);
}
if ( (_averageTop-_averageBottom)>_i2cVals[IDX_V_SENSITIVITY] && (_angleV+_i2cVals[IDX_V_STEP])<_i2cVals[IDX_V_ANGLE_MAX] ) {
// going up
delay(_slowingDelay);
for (int i=0; i < _i2cVals[IDX_V_STEP]; i++){
_servoV.write(_angleV++);
delay(_servoLoopDelay);
}
}
else if ( (_averageBottom-_averageTop)>_i2cVals[IDX_V_SENSITIVITY] && (_angleV-_i2cVals[IDX_V_STEP])>_i2cVals[IDX_V_ANGLE_MIN]) {
// going down
delay(_slowingDelay);
for (int i=0; i < _i2cVals[IDX_V_STEP]; i++){
_servoV.write(_angleV--);
delay(_servoLoopDelay);
}
}
else {
delay(_slowingDelay);
}
}
void moveServoToLimit(byte servoIdx, byte limitVal){
switch (servoIdx){
case CMD_IDX_HORI:
switch (limitVal){
case CMD_VAL_MIN:
_servoH.write(_i2cVals[IDX_H_ANGLE_MIN]);
break;
case CMD_VAL_MAX:
_servoH.write(_i2cVals[IDX_H_ANGLE_MAX]);
break;
default:
return;
}
break;
case CMD_IDX_VERT:
switch (limitVal){
case CMD_VAL_MIN:
_servoV.write(_i2cVals[IDX_V_ANGLE_MIN]);
break;
case CMD_VAL_MAX:
_servoV.write(_i2cVals[IDX_V_ANGLE_MAX]);
break;
default:
return;
}
break;
default:
return;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment