Skip to content

Commit

Permalink
Merge branch 'develop' for 5.3-RC1
Browse files Browse the repository at this point in the history
  • Loading branch information
sm6yvr committed Jun 7, 2018
2 parents 6a506d4 + 3b0c410 commit ad28370
Show file tree
Hide file tree
Showing 25 changed files with 975 additions and 726 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
Liam/LocalDefinition.h
.DS_Store
.vscode
*/.vs/
*/__vm/
*/Debug/
*.sln
*.vcxproj*
*.orig
*/Release/*
117 changes: 87 additions & 30 deletions Liam/BWFSensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,76 @@
Licensed under GPLv3
======================
*/
/*
The BWF sensor works by measuring the time between rising edges
Example:
Signal in BWF
I
^
| _ _
| | | | |
| | | | |
|...__| | _____| | ___...
| | | | |
| | | | |
| |_| |_|
|
+----------------------> t
1 1 5 1 1 5...
Outside of the fence, the sensor coil and amplifier circuit will sense the
rising edges in the signal. Inside the fence, the signal is inverted, and
the circuit will sense the falling edges of the signal instead.
In this example, the time between rising edges is 2 units, followed by 5,
2, 5, and so on. The time between falling edges is 7 units.
When a rising edge is detected on the currently selected sensor, the function
readSensor() is run. By keeping track of the last time it was run, it can
calculate the time between pulses and check if it matches what was expected
for being inside or outside of the fence.
*/

#include "BWFSensor.h"

int BWFSENSOR::outside_code[] = {OUTSIDE_BWF};
int BWFSENSOR::outside_code[] = {OUTSIDE_BWF, INSIDE_BWF-OUTSIDE_BWF};
int BWFSENSOR::inside_code[] = {INSIDE_BWF};

/** Specific constructor.
*/
int currentSensor = 0;

BWFSENSOR::BWFSENSOR(int selA, int selB) {
selpin_A = selA;
selpin_B = selB;
}


// select this sensor to be active
// Select active sensor
void BWFSENSOR::select(int sensornumber) {
if (currentSensor == sensornumber) {

return;
}
currentSensor = sensornumber;

digitalWrite(selpin_A, (sensornumber & 1) > 0 ? HIGH : LOW);
digitalWrite(selpin_B, (sensornumber & 2) > 0 ? HIGH : LOW);
clearSignal();
delay(200); // Wait a little to collect signal
long time = millis();
while (signal_status == NOSIGNAL
&& millis() - time < BWF_COLLECT_SIGNAL_TIME) // max time of 200ms
{
delay(1);
}

// delay(200);
}


void BWFSENSOR::clearSignal() {
for (int i=0; i<arr_length; i++)
arr[i]=0;
for (int i = 0; i < arr_length; i++)
arr[i] = 0;
signal_status = NOSIGNAL;
pulse_count_inside = 0;
pulse_count_outside = 0;
Expand All @@ -48,60 +92,73 @@ bool BWFSENSOR::isOutside() {
return (signal_status == OUTSIDE);
}

bool BWFSENSOR::isOutOfBounds() {
if (BWF_DETECTION_ALWAYS)
return !isInside();
else
return isOutside();
}

bool BWFSENSOR::isTimedOut() {
return (signal_status_checked + TIMEOUT_DELAY < millis());
return (last_match + TIMEOUT_DELAY < millis());
}

bool BWFSENSOR::hasNoSignal() {
return (signal_status_checked + NO_SIGNAL_DELAY < millis());
return (last_match + NO_SIGNAL_DELAY < millis());
}

// This routine is run at every timer interrupt and updates the sensor status

// This function is run each time the BWF pin gets a pulse
// For accuracy, this function should be kept as fast as possible
void BWFSENSOR::readSensor() {
volatile int pulse_unit = 0;
long now = micros();

// Calculate the time since last pulse
pulse_length = int(micros() - pulse_time);
pulse_time = micros();
pulse_unit = (pulse_length+half_unit_length) / pulse_unit_length;
int time_since_pulse = int(now - last_pulse);
last_pulse = now;


// Store the numbers for debug printout
arr[arr_count++] = pulse_unit;
if (arr_count>arr_length) arr_count=0;
// Convert to pulse units (rounding up)
int pulse_length = (time_since_pulse+(pulse_unit_length/2)) / pulse_unit_length;

// Check if the latest pulse fits the code for inside
if (abs(pulse_unit-inside_code[pulse_count_inside]) < 2) {
if (abs(pulse_length-inside_code[pulse_count_inside]) < 2) {
pulse_count_inside++;
// If the whole code sequence has been OK, then set signal status to 1

// Check if the entire pulse train has been batched
if (pulse_count_inside >= sizeof(inside_code)/sizeof(inside_code[0])) {
signal_status = INSIDE;
signal_status_checked = millis();
last_match = millis();
pulse_count_inside=0;
}
}
else
} else {
pulse_count_inside=0;
}

// Check if the latest pulse fits the code for outside
if (abs(pulse_unit-outside_code[pulse_count_outside]) < 2) {
if (abs(pulse_length-outside_code[pulse_count_outside]) < 2) {
pulse_count_outside++;
if (pulse_count_outside >= sizeof(outside_code)/sizeof(outside_code[0])) {
signal_status = OUTSIDE;
signal_status_checked = millis();
last_match = millis();
pulse_count_outside=0;
}
}
else
} else {
pulse_count_outside=0;
}


// Store the received code for debug output
arr[arr_count++] = pulse_length;
if (arr_count>arr_length) arr_count=0;
}

void BWFSENSOR::printSignal() {

for (int i=0; i<arr_length; i++) {
for (int i = 0; i < arr_length; i++) {
Serial.print(arr[i]);
Serial.print(" ");
}

}
bool BWFSENSOR::gotSignal()
{
return arr_count >= BWF_NUMBER_OF_PULSES ? true : false;
}
39 changes: 20 additions & 19 deletions Liam/BWFSensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,49 @@
#define OUTSIDE -1

// BWF Code for timout and no signal (in milliseconds)
#define TIMEOUT_DELAY 20000
#define NO_SIGNAL_DELAY 4000
#define TIMEOUT_DELAY 20000
#define NO_SIGNAL_DELAY 4000


class BWFSENSOR {
public:
BWFSENSOR(int selA, int selB);

void select(int sensornumber);
void clearSignal();

void attach(int intpin);
void readSensor();

bool isTimedOut();
bool isInside();
bool isOutside();
bool isTimedOut();
bool isOutOfBounds();
bool hasNoSignal();
bool gotSignal();

void printSignal();
void clearSignal();
void readSensor();

void printSignal();

private:
// BWF Code for inside and outside the fence
static int inside_code[];
static int outside_code[];

const static int pulse_unit_length = 100;

int pulse_count_inside;
int pulse_count_outside;

int selpin_A;
int selpin_B;
int counter;

int signal_status;
long last_interrupt;
long signal_status_checked;
long pulse_length;
long pulse_time;
int pulse_count_inside;
int pulse_count_outside;
int sensor_number;
const static int pulse_unit_length = 100;
const static int half_unit_length = 50;
long last_match;
long last_pulse;

// Array for debug printing
const static int arr_length=10;
int arr[arr_length];
int arr_count;

};

#endif /* _BWFSENSOR_H_ */
73 changes: 43 additions & 30 deletions Liam/Battery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
*/

#include "Battery.h"
#include "Definition.h"

/** Specific constructor.
*/
BATTERY::BATTERY(int type, int socpin, int dockpin) {
BATTERY::BATTERY(int type, int sensepin, int dockpin) {
batType = type;
batSocpin = socpin;
batDockpin = dockpin;
batSensePin = sensepin;
batDockPin = dockpin;

// Battery types are defined in Definition.h
// LIION
// NIMH
// LEAD_ACID

if (batType == LIION) {
fullyChargedLevel = LIIONFULL;
Expand All @@ -35,22 +39,22 @@ BATTERY::BATTERY(int type, int socpin, int dockpin) {
}


// set the level when battery is concidered fully charged
void BATTERY::setFullyChargedLevel(int level) {
fullyChargedLevel = level;
}

int BATTERY::getBatteryType() {
return batType;
}


// Set the voltage at which battery is considered fully charged (mV)
void BATTERY::setFullyChargedLevel(int level) {
fullyChargedLevel = level;
}

int BATTERY::getFullyChargedLevel() {
return fullyChargedLevel;
}


// set the level when battery is concidered depleted
// Set the voltage at which battery is considered depleted (mV)
void BATTERY::setDepletedLevel(int level) {
depletedLevel = level;
}
Expand All @@ -59,36 +63,45 @@ int BATTERY::getDepletedLevel() {
return depletedLevel;
}

int BATTERY::getSOC() {
return averageSOC;

bool BATTERY::mustCharge() {
return (averageVoltage < depletedLevel);
}

void BATTERY::resetSOC() {
averageSOC = readBatteryAndCalcValue();
bool BATTERY::isBeingCharged() {
return digitalRead(batDockPin);
}

bool BATTERY::mustCharge() {
return (averageSOC < depletedLevel);
bool BATTERY::isFullyCharged() {
return (readBatteryAndCalcValue() > fullyChargedLevel);
}


void BATTERY::updateSOC() {
averageSOC = averageSOC - (averageSOC / FILTER) + (readBatteryAndCalcValue() / FILTER);
// Get battery voltage in mV (filtered through running average)
int BATTERY::getVoltage() {
return averageVoltage;
}


word BATTERY::readBatteryAndCalcValue(){
unsigned long newReading = analogRead(batSocpin);
newReading = newReading * 488 * VOLTDIVATOR;
newReading /= 10000;
//return newReading;
return word(newReading);
void BATTERY::resetVoltage() {
averageVoltage = readBatteryAndCalcValue();
}

bool BATTERY::isBeingCharged() {
return digitalRead(batDockpin);
// Take a battery reading and recalculate running average
void BATTERY::updateVoltage() {
averageVoltage -= averageVoltage / FILTER;
averageVoltage += readBatteryAndCalcValue() / FILTER;
}

bool BATTERY::isFullyCharged() {
return (readBatteryAndCalcValue() > fullyChargedLevel);
// Measure battery voltage in mV
word BATTERY::readBatteryAndCalcValue(){
unsigned long reading = analogRead(batSensePin);

// Convert from ADC units to uV
reading = reading * 4880;
// Adjust for voltage divider circuit
reading = (reading * VOLTDIVATOR) / 10;
// Convert to mV
reading = reading / 1000;

return word(reading);
}
Loading

0 comments on commit ad28370

Please sign in to comment.