Last active
March 25, 2019 13:12
-
-
Save Conplug/9c5964295dfaa736057516caa6ab9627 to your computer and use it in GitHub Desktop.
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
// | |
// Copyright (c) 2019 Conplug (https://conplug.com.tw) | |
// Author: Hartman Hsieh | |
// | |
// Description : | |
// None | |
// | |
// Connections : | |
// Plug "DFRobot Gravity I2C LCD1602" module at "IIC0" of "NANO_EXP V1.0". | |
// Plug "DFRobot Gravity I2C DS1307 RTC" at "IIC1" of "NANO_EXP V1.0". | |
// Plug "MCP3423 V1.0" module at "IIC2" of "NANO_EXP V1.0". | |
// Plug "SDM_ADP V1.0" module at "SPI1" of "NANO_EXP V1.0". | |
// | |
// Required Library : | |
// https://github.com/uChip/MCP342X | |
// https://github.com/bearwaterfall/DFRobot_LCD-master | |
// | |
// | |
// IIC Address of MCP3423 | |
// | |
const int ADC_MCP_ADDRESS = 0x6E; | |
// | |
// SD card reader settings | |
// | |
const int SD_CARD_CHIP_SELECT_PIN = 6; // SD CARD SPI Chipset Select Pin | |
const String LogFileName = "vc.txt"; | |
// | |
// Save one record by the interval, unit is second. | |
// | |
const unsigned long UpdateInterval = 5 * 60; // seconds | |
// | |
// Resistance value of divider and shunt. unit is ohm. | |
// | |
const double RVH = 51.0 * 1000; // Resistance Divider | |
const double RVL = 1.1 * 1000; // Resistance Divider | |
const double RI = 0.005; // Shunt Resistance | |
// | |
// Current value needs to be corrected | |
// | |
const double CurrentCorrection = 1.83333; // current = CurrentCorrection * [original current value] | |
// | |
// DFROBOT_LCD : | |
// 1 - Using DFRobot's LCD 1602 module | |
// 2 - Using common LCD 1602 module | |
// | |
#define DFROBOT_LCD 0 | |
// | |
// MCP3423 | |
// | |
#include <Wire.h> | |
#include <MCP342X.h> | |
MCP342X AdcMcp (ADC_MCP_ADDRESS); | |
// | |
// IIC LCD Module | |
// | |
#if DFROBOT_LCD == 1 | |
#include "DFRobot_LCD.h" | |
DFRobot_LCD Lcd(16, 2); //16 characters and 2 lines of show | |
#else // #if DFROBOT_LCD == 1 | |
#include <LiquidCrystal_I2C.h> | |
LiquidCrystal_I2C Lcd (0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display | |
#endif // #if DFROBOT_LCD == 1 | |
// | |
// SD Card | |
// | |
#include <SPI.h> | |
#include <SD.h> | |
File SdFile; | |
Sd2Card Card; | |
// | |
// RTC DS1307 | |
// | |
//char* WeekDays[]={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}; | |
// | |
// Global variables | |
// | |
static int16_t Result1 = 0, Result2 = 0; | |
double Voltage = 0; | |
double Current = 0; | |
double PreVoltage = 0; | |
double PreCurrent = 0; | |
unsigned long CurrentTime = 0, PreviousTime = 0; | |
int LoopIndex = 0; | |
void setup() { | |
#if DFROBOT_LCD == 1 | |
Lcd.init(); | |
Lcd.display(); | |
#else // #if DFROBOT_LCD == 1 | |
Lcd.begin(); | |
Lcd.backlight(); | |
#endif // #if DFROBOT_LCD == 1 | |
Lcd.setCursor(0, 0); | |
Lcd.print(" "); | |
Lcd.setCursor(0, 1); | |
Lcd.print(" "); | |
Wire.begin(); // Join I2C bus | |
Serial.begin(9600); // Open serial connection to send info to the host | |
while (!Serial) {} // wait for Serial comms to become ready | |
Serial.println("Starting up"); | |
Serial.println("Testing device connection..."); | |
Serial.println(AdcMcp.testConnection() ? "MCP342X connection successful" : "MCP342X connection failed"); | |
// | |
// Init SD Card | |
// | |
pinMode (SD_CARD_CHIP_SELECT_PIN, OUTPUT); | |
if (!Card.init(SPI_HALF_SPEED, SD_CARD_CHIP_SELECT_PIN)) { | |
Serial.println("initialization failed. Check: SD Card"); | |
return; | |
} else { | |
Serial.println("============= Card Information =================="); | |
} | |
// | |
// Print Card Type | |
// | |
Serial.print("Card type: "); | |
switch (Card.type()) { | |
case SD_CARD_TYPE_SD1: | |
Serial.println("SD1"); | |
break; | |
case SD_CARD_TYPE_SD2: | |
Serial.println("SD2"); | |
break; | |
case SD_CARD_TYPE_SDHC: | |
Serial.println("SDHC"); | |
break; | |
default: | |
Serial.println("Unknow"); | |
} | |
Serial.println("Initializing SD card..."); | |
if (!SD.begin(SD_CARD_CHIP_SELECT_PIN)) { | |
Serial.println("initialization failed!"); | |
while (1); | |
} | |
Serial.println("initialization done."); | |
} // End of setup() | |
void loop() { | |
int Rtc[7] = {0}; | |
unsigned long file_size = 0; | |
SdFile = SD.open(LogFileName, FILE_READ); | |
file_size = SdFile.size(); | |
SdFile.close(); | |
// | |
// Read data from channel 1 for voltage | |
// | |
AdcMcp.configure( MCP342X_MODE_CONTINUOUS | | |
MCP342X_CHANNEL_1 | | |
MCP342X_SIZE_16BIT | | |
MCP342X_GAIN_1X | |
); | |
AdcMcp.startConversion(); | |
AdcMcp.getResult(&Result1); | |
// | |
// From MCP3423 spec. | |
// http://ww1.microchip.com/downloads/en/DeviceDoc/22088b.pdf | |
// | |
// On-Board(MCP3423) Voltage Reference (V REF): | |
// - Accuracy: 2.048V +- 0.05% | |
// | |
// MINIMUM AND MAXIMUM OUTPUT CODES | |
// +--------------------------------------------------------------+ | |
// | Resolution Setting | Data Rate | Minimum Code | Maximum Code | | |
// +--------------------------------------------------------------+ | |
// | 16 | 15 SPS | -32768 | 32767 | | |
// +--------------------------------------------------------------+ | |
// | |
// Calculate voltage | |
// | |
Voltage = (((RVH + RVL) * 2.048) / (RVL * 32767.0)) * Result1; | |
// | |
// Read data from channel 2 for current | |
// | |
AdcMcp.configure( MCP342X_MODE_CONTINUOUS | | |
MCP342X_CHANNEL_2 | | |
MCP342X_SIZE_16BIT | | |
MCP342X_GAIN_1X | |
); | |
AdcMcp.startConversion(); | |
AdcMcp.getResult(&Result2); | |
// | |
// See above table and calculate current | |
// | |
Current = ((2.048 * Result2) / 32767.0) / RI; | |
Current *= CurrentCorrection; | |
if (Current >= -0.02 && Current <= 0.02) Current = 0.0; | |
// | |
// Get data from RTC DS1307 | |
// | |
RtcGet(Rtc); | |
Lcd.setCursor(0, 0); | |
Lcd.print(Voltage); | |
Lcd.print("V,"); | |
Lcd.print(Current); | |
Lcd.print("A"); | |
Lcd.print(" "); | |
//Lcd.setCursor(13, 0); | |
//Lcd.print(WeekDays[Rtc[3] - 1]); | |
Lcd.setCursor(0, 1); | |
if ((LoopIndex / 30) % 2 == 0) { // Every 30 loop, exchange display. | |
Lcd.print("Size = "); | |
Lcd.print(file_size); | |
Lcd.print(" "); | |
} | |
else { | |
PrintDigits(&Lcd, Rtc[5]); // MONTH | |
Lcd.print("-"); | |
PrintDigits(&Lcd, Rtc[4]); // DATE | |
Lcd.print(" "); | |
PrintDigits(&Lcd, Rtc[2]); // HOUR | |
Lcd.print(":"); | |
PrintDigits(&Lcd, Rtc[1]); // MIN | |
Lcd.print(":"); | |
PrintDigits(&Lcd, Rtc[0]); // SEC | |
Lcd.print(" "); | |
} | |
// | |
// If voltage or current changes, save one record. | |
// | |
if ((abs(Voltage - PreVoltage) >= 0.02) || (abs(Current - PreCurrent) >= 0.02)) { | |
SaveToSd(Voltage, Current); | |
PreVoltage = Voltage; | |
PreCurrent = Current; | |
PreviousTime = millis(); | |
} | |
else { | |
CurrentTime = millis(); | |
// | |
// Save one record by the interval, unit is second. | |
// | |
if ((PreviousTime == 0) || ((CurrentTime - PreviousTime) > (UpdateInterval * 1000))) { | |
SaveToSd(Voltage, Current); | |
PreviousTime = CurrentTime; | |
} | |
} | |
LoopIndex++; | |
if (LoopIndex >= 99) LoopIndex = 0; // This yields a range of -32,768 to 32,767 (minimum value of -2^15 and a maximum value of (2^15) - 1) | |
} // End of loop() | |
void SaveToSd(double Voltage, double Current) | |
{ | |
int Rtc[7] = {0}; | |
// | |
// Get data from RTC DS1307 | |
// | |
RtcGet(Rtc); | |
SdFile = SD.open(LogFileName, FILE_WRITE); | |
SdFile.print(Rtc[6]); // YEAR | |
SdFile.print("-"); | |
PrintDigits(&SdFile, Rtc[5]); // MONTH | |
SdFile.print("-"); | |
PrintDigits(&SdFile, Rtc[4]); // DATE | |
SdFile.print(" "); | |
PrintDigits(&SdFile, Rtc[2]); // HOUR | |
SdFile.print(":"); | |
PrintDigits(&SdFile, Rtc[1]); // MIN | |
SdFile.print(":"); | |
PrintDigits(&SdFile, Rtc[0]); // SEC | |
SdFile.print(","); | |
SdFile.print(Voltage, 6); | |
SdFile.print(","); | |
SdFile.println(Current, 6); | |
SdFile.flush(); | |
SdFile.close(); | |
Serial.print(Rtc[6]); // YEAR | |
Serial.print("-"); | |
PrintDigits(&Serial, Rtc[5]); // MONTH | |
Serial.print("-"); | |
PrintDigits(&Serial, Rtc[4]); // DATE | |
Serial.print(" "); | |
PrintDigits(&Serial, Rtc[2]); // HOUR | |
Serial.print(":"); | |
PrintDigits(&Serial, Rtc[1]); // MIN | |
Serial.print(":"); | |
PrintDigits(&Serial, Rtc[0]); // SEC | |
Serial.print(","); | |
Serial.print(Voltage, 6); | |
Serial.print(","); | |
Serial.println(Current, 6); | |
} | |
void PrintDigits(Print* pPrint, int digits) | |
{ | |
if (digits < 10) | |
pPrint->print('0'); | |
pPrint->print(digits); | |
} | |
#define DS1307_CTRL_ID B1101000 // DS1307 | |
bool RtcGet(int* Rtc) | |
{ | |
uint8_t RtcBcd[7]; | |
Wire.beginTransmission(DS1307_CTRL_ID); | |
Wire.write((uint8_t)0x00); | |
Wire.endTransmission(); | |
// | |
// Read the registers | |
// Seconds, Minutes, Hours, Day Of Week, Date, Month, Year | |
// | |
Wire.requestFrom(DS1307_CTRL_ID, 7); | |
for(int i = 0; i < 7; i++) | |
{ | |
RtcBcd[i] = Wire.read(); | |
} | |
Rtc[0] = Bcd2Dec(RtcBcd[0] & 0x7f); // Seconds | |
Rtc[1] = Bcd2Dec(RtcBcd[1]); // Minutes | |
Rtc[2] = Bcd2Dec(RtcBcd[2] & 0x3f); // Hours | |
Rtc[3] = Bcd2Dec(RtcBcd[3]); // Day Of Week | |
Rtc[4] = Bcd2Dec(RtcBcd[4]); // Date | |
Rtc[5] = Bcd2Dec(RtcBcd[5]); // Month | |
Rtc[6] = Bcd2Dec(RtcBcd[6]) + 2000; // Year | |
} | |
// | |
// Convert Binary Coded Decimal (BCD) to Decimal | |
// | |
uint8_t Bcd2Dec(uint8_t Bcd) | |
{ | |
return ((Bcd / 16 * 10) + (Bcd % 16)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment