Last active
May 22, 2018 02:28
-
-
Save IOT-123/a6132924e753e993ed8da11f60a7d1d1 to your computer and use it in GitHub Desktop.
Used for I2C BRICK.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* | |
* IOT123 ATTINY85 I2C SLAVE AUTO-JOIN LAYER FOR SENSOR: MAX9812 | |
* | |
* Take readings on MAX9812 and send across wire on request via I2C in 3 segment 16byte packets | |
* ID of PROPERTY (set in _properties) | |
* VALUE of PROPERTY (set in getProperties) | |
* MORE TO COME (0/1 0 = last property) | |
* | |
* Pins on ATTINY85 | |
* SDA PB0 | |
* SCL PB2 | |
* MAX9812 A3 | |
*/ | |
#include <Wire.h> //SDA pin5/PB0, SCL pin7/PB2 | |
#define arraySize(x) (sizeof(x) / sizeof(x[0])) | |
#define NVC_NUM_STAGES 3 | |
//------------------------------SENSOR SPECIFIC DECLARATIONS | |
//#define _micSamples (1024*2) | |
#define _micSamples (512) | |
#define ADDRESS_SLAVE 11 | |
#define PIN_SENSOR A3 | |
//--------------------------END SENSOR SPECIFIC DECLARATIONS | |
#define TIME_RESPONSE_MS 0 // will be last value sent to master + padding | |
#if (TIME_RESPONSE_MS) | |
unsigned long startMillis; | |
#endif | |
struct nvc | |
{ | |
char Name[16]; | |
char Value[16]; | |
bool Continue; | |
}; | |
//------------------------------SENSOR SPECIFIC METADATA | |
//nvc _metas[8] = { | |
// {"ASSIM_NAME", "MAX9812", true}, | |
// {"ASSIM_VERSION", "1", true}, | |
// {"ASSIM_ROLE", "SENSOR", true}, | |
// {"POWER_DOWN", "1", true}, | |
// {"PREPARES", "0", true}, | |
// {"RESPONSE_MS", "50", true}, | |
// {"MQTT_TOPIC", "MICROPHONE", true}, | |
// {"VCC_MV", "", false} // ALWAYS HAVE THIS LAST | |
//}; | |
#define META_COUNT 9 | |
const static char m1[] PROGMEM = "ASSIM_NAME"; | |
const static char m2[] PROGMEM = "MAX9812"; | |
const static char m3[] PROGMEM = "1"; | |
const static char m4[] PROGMEM = "ASSIM_VERSION"; | |
const static char m5[] PROGMEM = "1"; | |
const static char m6[] PROGMEM = "1"; | |
const static char m7[] PROGMEM = "ASSIM_ROLE"; | |
const static char m8[] PROGMEM = "SENSOR"; | |
const static char m9[] PROGMEM = "1"; | |
const static char m10[] PROGMEM = "POWER_DOWN"; | |
const static char m11[] PROGMEM = "1"; | |
const static char m12[] PROGMEM = "1"; | |
const static char m13[] PROGMEM = "PREPARE_MS"; | |
const static char m14[] PROGMEM = "0"; | |
const static char m15[] PROGMEM = "1"; | |
const static char m16[] PROGMEM = "RESPONSE_MS"; | |
const static char m17[] PROGMEM = "500"; | |
const static char m18[] PROGMEM = "1"; | |
const static char m19[] PROGMEM = "CLOCK_STRETCH"; | |
const static char m20[] PROGMEM = "80000"; | |
const static char m21[] PROGMEM = "1"; | |
const static char m22[] PROGMEM = "MQTT_TOPIC"; | |
const static char m23[] PROGMEM = "MICROPHONE"; | |
const static char m24[] PROGMEM = "1"; | |
const static char m25[] PROGMEM = "VCC_MV"; | |
const static char m26[] PROGMEM = ""; | |
const static char m27[] PROGMEM = "0"; | |
const char* const _metas[] PROGMEM = { m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27 }; | |
//--------------------------END SENSOR SPECIFIC METADATA | |
//------------------------------SENSOR SPECIFIC PROPERTIES | |
nvc _props[3] ={ | |
{"audMin (0-1023)", "", true}, | |
{"audMax (0-1023)", "", true}, | |
{"audDiff (0-50)", "", false} | |
}; | |
//--------------------------END SENSOR SPECIFIC PROPERTIES | |
volatile int _packetStage = 0; | |
volatile int _propertyIndex = 0; | |
volatile bool _metasConfirmed = false; | |
volatile int _metaIndex = 0; | |
uint16_t _vcc; | |
void setup() | |
{ | |
_vcc = getVcc(); | |
Wire.begin(ADDRESS_SLAVE); | |
Wire.onReceive(receiveEvent); | |
Wire.onRequest(requestEvent); | |
} | |
void loop() | |
{ | |
} | |
void receiveEvent (int howMany) | |
{ | |
byte buf[10]; | |
int i; | |
for (i=0; i<howMany; i++) | |
{ | |
buf[i] = Wire.read(); // receive byte as a character | |
} | |
if((buf[0] == 1) && (howMany == 1)){ | |
_metasConfirmed = true; | |
_packetStage = 0; | |
_propertyIndex = 0; | |
} | |
} | |
void requestEvent() { | |
char currentPacket[16]; | |
int propCount = 0; | |
if (_metasConfirmed){ | |
// PROPERTIES | |
if (_propertyIndex == 0){ | |
getProperties(); | |
} | |
strcpy(currentPacket, nvcAsCharArray(_props[_propertyIndex], _packetStage)); | |
propCount = arraySize(_props); | |
// METADATA | |
}else{ | |
propCount = META_COUNT; | |
if (_metaIndex == ((META_COUNT * 3) - 2)){// if last metadata (VCC), only runtime entry | |
itoa(_vcc, currentPacket, 10); | |
}else{ // just a normal metadata item | |
//itoa(_metaIndex, currentPacket, 10); | |
strcpy_P(currentPacket, (char*)pgm_read_word(&(_metas[_metaIndex]))); | |
} | |
_metaIndex++; | |
} | |
Wire.write(currentPacket); // send metadate or sensor property | |
_packetStage = _packetStage + 1; | |
// go to next property if at last stage of current property | |
if (_packetStage == NVC_NUM_STAGES){ | |
_packetStage = 0; | |
_propertyIndex++; | |
} | |
// all properties processed? | |
if (_propertyIndex == propCount){ | |
_propertyIndex = 0; | |
// "0" should terminate requests to this slave | |
} | |
} | |
//------------------------------SENSOR SPECIFIC PROPERTY READING | |
void getProperties(){ | |
#if (TIME_RESPONSE_MS) | |
startMillis = millis(); | |
#endif | |
// read sensor | |
unsigned int peakToPeak = 0; // peak-to-peak level | |
unsigned int signalMax = 0; | |
unsigned int signalMin = 1024; | |
// collect data for 50 mS | |
for (int i = 0; i < _micSamples; i++) // does not like millis! | |
{ | |
int k = analogRead(PIN_SENSOR); | |
signalMin = min(signalMin, k); | |
signalMax = max(signalMax, k); | |
} | |
peakToPeak = signalMax - signalMin; // max - min = peak-peak amplitude | |
// put values in table | |
itoa(signalMin, _props[0].Value, 10); | |
itoa(signalMax, _props[1].Value, 10); | |
itoa(peakToPeak, _props[2].Value, 10); | |
} | |
//--------------------------END SENSOR SPECIFIC PROPERTY READING | |
char* nvcAsCharArray(nvc nvc, int packetStage){ | |
switch (packetStage){ | |
case 0: | |
return nvc.Name; | |
break; | |
case 1: | |
#if (TIME_RESPONSE_MS) | |
unsigned long currentMillis; | |
currentMillis = millis(); | |
char millis[16]; | |
itoa(currentMillis - startMillis, millis, 10); | |
return millis; | |
#endif | |
return nvc.Value; | |
break; | |
case 2: | |
return nvc.Continue ? "1" : "0"; | |
break; | |
default: | |
char result[16]; | |
itoa(packetStage, result, 10); | |
return result; | |
} | |
} | |
// https://www.avrfreaks.net/forum/attiny85-vcc-measurement-skews-higher-vcc-voltages | |
//5v = 6393, 6504 | |
//3.3V 3430 | |
uint16_t getVcc() { | |
// Read 1.1V reference against AVcc | |
// set the reference to Vcc and the measurement to the internal 1.1V reference | |
ADMUX = _BV(MUX3) | _BV(MUX2); | |
delay(2); // Wait for Vref to settle | |
uint16_t result = 0; | |
for (int x = 0; x < 32; x++){ | |
ADCSRA |= _BV(ADSC); // Start conversion | |
while (bit_is_set(ADCSRA,ADSC)); // measuring | |
if (x > 15){ | |
result += (int16_t)((int16_t)(ADC - result) / 2); | |
} | |
else{ | |
result = ADC; | |
} | |
} | |
uint16_t voltage = 1125300 / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 | |
return voltage; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment