Skip to content

Instantly share code, notes, and snippets.

@IOT-123
Last active May 22, 2018 02:28
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/a6132924e753e993ed8da11f60a7d1d1 to your computer and use it in GitHub Desktop.
Save IOT-123/a6132924e753e993ed8da11f60a7d1d1 to your computer and use it in GitHub Desktop.
Used for I2C BRICK.
/*
*
* 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