Commit 2a7b6874 authored by Patrick's avatar Patrick

moved examples into this repo with red_peg library

parent 9e057180
#include <SPI.h>
#include <SdFat.h>
//#include <red_peg.h>
#define RP_SD_SS 5
#define BAUD 115200
SdFat SD;
File myFile;
//red_peg RP;
void setup() {
Serial.begin(BAUD);
Serial.println(F("starting rp_sd_logging"));
Serial.print(F("initialise SD card…"));
pinMode(10, OUTPUT);
if (!SD.begin(RP_SD_SS)) {
Serial.println("initialization failed!");
// do nothing forever
//while (1);
}
Serial.println("initialization done.");
//RP.begin();
}
void loop() {
//t_SensorData depth = RP.get(MA4_20);
// if (depth.sensor == MA4_20) {
// Serial.print("Value: ");
// Serial.print(depth.reading);
// Serial.print(", ");
// Serial.print(RP.mA(depth));
// Serial.print(" mA, ");
// Serial.print(RP.level(depth, 7000));
// Serial.print(" mm");
// Serial.println();
// } else {
Serial.println("no return from ADC");
// }
delay(1000);
}
#include <red_peg.h>
red_peg RP;
#define SENSOR_ACTIVE_PIN 6
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(BAUD);
Serial.println(F("start rp_sensor_active_blink"));
delay(100);
RP.begin();
}
// the loop function runs over and over again forever
void loop() {
RP.sensorsOn();
delay(1000); // wait for a second
RP.sensorsOff();
delay(1000); // wait for a second
}
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
void setup () {
Serial.begin(115200);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
}
void loop () {
DateTime now = rtc.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(" (");
Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
Serial.print(") ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
Serial.print(" since midnight 1/1/1970 = ");
Serial.print(now.unixtime());
Serial.print("s = ");
Serial.print(now.unixtime() / 86400L);
Serial.println("d");
// calculate a date which is 7 days and 30 seconds into the future
DateTime future (now + TimeSpan(7,12,30,6));
Serial.print(" now + 7d + 30s: ");
Serial.print(future.year(), DEC);
Serial.print('/');
Serial.print(future.month(), DEC);
Serial.print('/');
Serial.print(future.day(), DEC);
Serial.print(' ');
Serial.print(future.hour(), DEC);
Serial.print(':');
Serial.print(future.minute(), DEC);
Serial.print(':');
Serial.print(future.second(), DEC);
Serial.println();
Serial.println();
delay(3000);
}
Red-Peg
-------
Arduino library for communication with the [red-peg shield](https://git.defproc.co.uk/ea/red-peg).
# Functions
To use the library, include it and create the constructor with a name that you
can remember.
```
#include <red_peg.h>
red_peg RP;
```
To use the library, call the `begin` function during `setup()`:
```
RP.begin();
```
This allows a new variable type that stores all the received data from the
red-peg slave controller: `t_SensorData`
And the functions available are:
* `t_SensorData returnedValue = RP.get(SENSOR_NAME);`
* `RP.sensorsOn()`
* `RP.sensorsOff()`
A set of helper functions will work on the `returnedValue` data to give more
useful results:
* `RP.print_data(returnedValue)`
* `RP.degC(returnedValue)`
* `RP.volts(returnedValue)`
* `RP.mA(returnedValue)`
* `RP.level(returnedValue, max_level)`
Sensor control is made by asking for one of the sensor values. `SENSOR_NAME`
options are:
* `RTC`
* `ADC1` which is equal to `MA4_20`
* `ADC2` which is equal to `ANA`
* `ADC3` which is equal to `TMP`
* `SDI` (unused)
......@@ -8,8 +8,6 @@ void setup() {
}
void loop() {
Morse.print("cq");
delay(2000);
Morse.write('k');
delay(2000);
}
......@@ -17,7 +17,6 @@ void loop () {
Serial.print(the_time.m);
Serial.print("-");
Serial.print(the_time.d);
Serial.print("-");
Serial.print("T");
Serial.print(the_time.hh);
Serial.print(":");
......
......@@ -19,7 +19,6 @@ void setup()
die();
}
reportTimeNow();
Serial.println();
Serial.println(F("To set the time send \"T YYYY MM DD hh mm s\""));
}
......@@ -76,13 +75,13 @@ void reportTimeNow() {
char buf[5];
sprintf(buf, "%04d", now.year());
Serial.print(buf);
Serial.write('/');
Serial.write('-');
sprintf(buf, "%02d", now.month());
Serial.print(buf);
Serial.write('/');
Serial.write('-');
sprintf(buf, "%02d", now.day());
Serial.print(buf);
Serial.write('-');
Serial.write('T');
sprintf(buf, "%02d", now.hour());
Serial.print(buf);
Serial.write(':');
......@@ -91,5 +90,6 @@ void reportTimeNow() {
Serial.write(':');
sprintf(buf, "%02d", now.second());
Serial.print(buf);
//Serial.println();
Serial.write('Z');
Serial.println();
}
name=Red-Peg
version=0.1
author=Patrick Fenner <contact@defproc.co.uk>
maintainer=Def-Proc Engineering <contact@defproc.co.uk>
sentence=A library and examples to run the Red-Peg sensor board
paragraph=A library to run the Red-Peg sensor board and examples for teaching.
category=Device Control
url=http://defproc.co.uk/red-peg
architectures=*
includes=red_peg.h
#include "Wire.h"
#include "MCP342x.h"
#include "Arduino.h"
// Assuming a 100kHz clock the address and config byte take 18 clock
// cycles, or 180 microseconds. Use a timeout of 250us to be safe.
const MCP342x::Channel MCP342x::channel1 = Channel(0x00);
const MCP342x::Channel MCP342x::channel2 = Channel(0x20);
const MCP342x::Channel MCP342x::channel3 = Channel(0x40);
const MCP342x::Channel MCP342x::channel4 = Channel(0x60);
const MCP342x::Mode MCP342x::oneShot = Mode(0x00);
const MCP342x::Mode MCP342x::continous = Mode(0x10);
const MCP342x::Resolution MCP342x::resolution12 = Resolution(0x00);
const MCP342x::Resolution MCP342x::resolution14 = Resolution(0x04);
const MCP342x::Resolution MCP342x::resolution16 = Resolution(0x08);
const MCP342x::Resolution MCP342x::resolution18 = Resolution(0x0c);
const MCP342x::Gain MCP342x::gain1 = Gain(0x00);
const MCP342x::Gain MCP342x::gain2 = Gain(0x01);
const MCP342x::Gain MCP342x::gain4 = Gain(0x02);
const MCP342x::Gain MCP342x::gain8 = Gain(0x03);
uint8_t MCP342x::generalCallReset(void)
{
Wire.beginTransmission(0x00);
Wire.write(0x06);
return Wire.endTransmission();
}
uint8_t MCP342x::generalCallLatch(void)
{
Wire.beginTransmission(0x00);
Wire.write(0x04);
return Wire.endTransmission();
}
uint8_t MCP342x::generalCallConversion(void)
{
Wire.beginTransmission(0x00);
Wire.write(0x08);
return Wire.endTransmission();
}
void MCP342x::normalise(long &result, Config config)
{
/* Resolution is 12, 14, 16,or 18; gain is 1, 2, 4, or 8. Shift
* least places necessary such that all possibilities can be
* accounted for:
*
* 18 - resolution + 3 - log2(gain)
*
* Largest shift is for resolution==12 and gain==1 (9 places)
* Smallest is for resolution==18 and gain==8 (0 places) This means
* that the lowest 21 bits of the long result are used and that up
* to 1024 results can be safely accumulated without
* underflow/overflow.
*/
result <<= (21 - int(config.getResolution()) - config.getGain().log2());
}
MCP342x::MCP342x(void) : address(0x68)
{
;
}
MCP342x::MCP342x(uint8_t add) : address(add)
{
;
}
bool MCP342x::autoprobe(const uint8_t *addressList, uint8_t len)
{
for (uint8_t i = 0; i < len; ++i) {
Wire.requestFrom(addressList[i], (uint8_t)1);
if (Wire.available()) {
address = addressList[i];
return true;
}
}
return false;
}
/** Initiate a conversion by writing to the configuration register
*/
MCP342x::error_t MCP342x::convert(Channel channel, Mode mode, Resolution resolution, Gain gain)
{
return convert(Config(channel, mode, resolution, gain));
}
MCP342x::error_t MCP342x::configure(const Config &config) const
{
Wire.beginTransmission(address);
Wire.write(config.val);
if (Wire.endTransmission())
return errorConfigureFailed;
else
return errorNone;
}
MCP342x::error_t MCP342x::convert(const Config &config) const
{
Wire.beginTransmission(address);
Wire.write(config.val | newConversionMask);
if (Wire.endTransmission())
return errorConvertFailed;
else
return errorNone;
}
MCP342x::error_t MCP342x::read(long &result, Config& status) const
{
// Read 4 bytes, the 4th byte will configuration. From that deduce
// if 18 bit conversion. If not use the 3rd byte, as that is the
// most appropriate configuration value (ready may have changed).
const uint8_t len = 4;
uint8_t buffer[len] = {};
Wire.requestFrom(address, len);
if (Wire.available() != len)
return errorReadFailed;
for (uint8_t i = 0; i < len; ++i)
buffer[i] = Wire.read();
uint8_t dataBytes;
if ((buffer[3] & 0x0c) == 0x0c) {
status = Config(buffer[3]); // 18 bit conversion
dataBytes = 3;
}
else {
status = Config(buffer[2]);
dataBytes = 2;
}
if ((status & notReadyMask) != 0)
return errorConversionNotReady;
long signBit = 0; // Location of sign bit
long signExtend = 0; // Bits to be set if sign is set
switch (int(status.getResolution())) {
case 12:
signBit = 0x800;
signExtend = 0xFFFFF000;
break;
case 14:
signBit = 0x2000;
signExtend = 0xFFFFC000;
break;
case 16:
signBit = 0x8000;
signExtend = 0xFFFF0000;
break;
case 18:
signBit = 0x20000;
signExtend = 0xFFFC0000;
break;
}
result = 0;
for (uint8_t i = 0; i < dataBytes; ++i) {
result <<= 8;
result |= (long)buffer[i];
}
// Fill/blank remaining bits
if ((result & signBit) != 0)
result |= signExtend; // Sign bit is set, sign-extend
return errorNone;
}
MCP342x::error_t MCP342x::convertAndRead(Channel channel, Mode mode, Resolution resolution, Gain gain, unsigned long timeout, long &result, Config &status)
{
error_t err = convert(channel, mode, resolution, gain);
if (err != errorNone)
return err;
unsigned long t = micros() + timeout;
unsigned long convTime = resolution.getConversionTime();
if (convTime > 16383) {
// Unreliable (see arduino reference), use delay() instead
convTime /= 1000;
delay(convTime);
}
else
delayMicroseconds(convTime);
do {
err = read(result, status);
if (!err && status.isReady())
return err;
} while (long(micros() - t) >= 0);
return errorReadTimeout;
}
int16_t MCP342x::getAdc(Channel the_channel) {
long adc_reading = 0;
uint16_t timeout = 10000;
MCP342x::Config status;
MCP342x::error_t err = convertAndRead(the_channel, MCP342x::oneShot, MCP342x::resolution16, MCP342x::gain1, timeout, adc_reading, status);
//if (err) {
//return (long)-err;
//} else {
// make sure the reading is positive (!)
//adc_reading = abs(adc_reading);
return (int16_t)adc_reading;
//return errNone;
//}
}
unsigned long MCP342x::Resolution::getConversionTime(void) const
{
switch ((int)(*this)) {
case 12:
return 4167; // 240 SPS
case 14:
return 16667; // 60 SPS
case 16:
return 66667; // 15 SPS
case 18:
return 266667; // 3.75 SPS
}
return 0; // Shouldn't happen
}
unsigned long MCP342x::Config::getConversionTime(void) const
{
return Resolution(val).getConversionTime();
// switch ((int)getResolution()) {
// case 12:
// return 4167; // 240 SPS
// case 14:
// return 16667; // 60 SPS
// case 16:
// return 66667; // 15 SPS
// case 18:
// return 266667; // 3.75 SPS
// }
// return 0; // Shouldn't happen
}
#ifndef MCP342X_h
#define MCP342X_h
#define MCP342X_VERSION "1.0.2"
#define MCP3428 0x6F
#define MCP_ADC1 MCP342x::channel1
#define MCP_ADC2 MCP342x::channel2
#define MCP_ADC3 MCP342x::channel3
#define MCP_ADC4 MCP342x::channel4
class MCP342x {
public:
class Config;
class Channel;
class Mode;
class Resolution;
class Gain;
static const Channel channel1;
static const Channel channel2;
static const Channel channel3;
static const Channel channel4;
static const Mode oneShot;
static const Mode continous;
static const Resolution resolution12;
static const Resolution resolution14;
static const Resolution resolution16;
static const Resolution resolution18;
static const Gain gain1;
static const Gain gain2;
static const Gain gain4;
static const Gain gain8;
static const uint8_t notReadyMask = 0x80;
static const uint8_t newConversionMask = 0x80;
static const uint8_t numChannels = 4;
static const uint8_t maxResolution = 18;
static const uint8_t maxGain = 8;
static const int writeTimeout_us = 250;
enum error_t {
errorNone,
errorConvertFailed,
errorReadFailed,
errorReadTimeout,
errorConversionNotReady,
errorConfigureFailed,
};
static uint8_t generalCallReset(void);
static uint8_t generalCallLatch(void);
static uint8_t generalCallConversion(void);
// Adjust result to account for gain and resolution settings
static void normalise(long &result, Config config);
MCP342x(void);
MCP342x(uint8_t address);
bool autoprobe(const uint8_t *addressList, uint8_t len);
/** Return the I2C address used for communicating with this device.
*/
uint8_t getAddress(void) const {
return address;
}
/** Configure the device. Useful only for generalCallConversion()
*/
error_t configure(const Config &config) const;
/** Instruct the MCP342x device to begin a conversion.
* @param channel The ADC channel, one of channel0, channel1,
* channel2 or channel3. Not all supported devices have 4
* channels.
* @param mode The conversion mode, oneShot or continous.
* @param resolution Number of bits in the result, one of res12,
* res14, res16 or res18. Not all devices support 18-bit resolution.
* @param gain The gain setting of the programmable gain amplifier,
* one of gain1, gain2, gain4 or gain8.
* @return Value indicating error (if any).
*/
error_t convert(Channel channel, Mode mode, Resolution resolution, Gain gain); error_t convert(const Config &config) const;
/** Read the sample value from the MCP342x device.
* @param result The signed result.
* @param config The contents of the configuration register.
* @return Value indicating error (if any).
*/
error_t read(long &result, uint8_t& config) const;
error_t read(long &result, Config& config) const;
/** Instruct the MCP342x device to begin a conversion and block
* until read completes or timed out.
* @param channel The ADC channel, one of channel0, channel1,
* channel2 or channel3. Not all supported devices have 4
* channels.
* @param mode The conversion mode, oneShotMode or continousMode.
* @param resolution Number of bits in the result, one of res12,
* res14, res16 or res18. Not all devices support 18-bit resolution.
* @param gain The gain setting of the programmable gain amplifier,
* one of gain1, gain2, gain4 or gain8.
* @param timeout The time out value in microseconds.
* @param result The signed result.
* @param config The contents of the configuration register.
* @return Value indicating error (if any).
*/
error_t convertAndRead(Channel channel, Mode mode, Resolution resolution, Gain gain, unsigned long timeout, long &result, Config &status);
/* DefProc added functions:
getAdc: read the ADC with 16bit, gain1, timeout 10 seconds
* @param the_channel one of: MCP_ADC(1,2,3,4)
* @return value (if positive) or error number (if negative)
*/
//error_t getAdc(Channel the_channel, long &adc_reading);
int16_t getAdc(Channel the_channel);
private:
uint8_t address;
// For easy readout need to know whether 18 bit mode was selected
// uint8_t config;
};
class MCP342x::Channel {
friend class MCP342x;
friend class MCP342x::Config;
public:
inline operator int(void) const {
return (val >> 5) + 1;
}
private:
inline Channel(uint8_t v) : val(v & 0x60) {
};
uint8_t val;
};
class MCP342x::Mode {
friend class MCP342x;
friend class MCP342x::Config;
public:
//inline operator int(void) const {
//return (val >> 1) + 12;
//}
private:
inline Mode(uint8_t v) : val(v & 0x10) {
};
uint8_t val;
};
class MCP342x::Resolution {
friend class MCP342x;
friend class MCP342x::Config;
public:
inline operator int(void) const {
return (val >> 1) + 12;
}
unsigned long getConversionTime(void) const;
private:
inline Resolution(uint8_t v) : val(v & 0x0c) {
};
uint8_t val;
};
class MCP342x::Gain {
friend class MCP342x;
friend class MCP342x::Config;
public:
inline operator int(void) const {
return (1 << val);
}
inline uint8_t log2(void) const {
return val;
}
private:
inline Gain(uint8_t v) : val(v & 0x03) {
};
uint8_t val;
};
class MCP342x::Config {
friend class MCP342x;
public:
inline Config(void) : val(0) {
};
inline Config(uint8_t v) : val(v) {
};
inline Config(Channel c, Mode m, Resolution r, Gain g) :
val(c.val | m.val | r.val | g.val) {
};
inline Config(uint8_t c, bool continuous, uint8_t r, uint8_t g) :
val((((c-1) & 3) << 5)
| (uint8_t)(continuous ? 0x10 : 0)
| ((((r-12) & 0x1e) << 1) & 0xc)) {
switch(g) {
case 2:
val |= 0x01;
break;
case 4:
val |= 0x02;
break;
case 8:
val |= 0x03;
break;