Hello there guys,
there is this project on the internet, Arduino based Milliohm Meter. I want to replicate the project, but don't need "Scale 0m1: 0.1mOhm to 12.9999 Ohm". I wrote an E-Mail to author already, but still no answer 2 weeks later. Furthermore, I tried it by myself, but I have not enough knowledge how to do it, so at the end code stopped working ![]()
Could you guys help me and completely remove scale 0m1: 0.1mOhm to 12.9999 Ohm part from this code:
#include <Wire.h>
#include <EEPROM.h>
#include <hd44780.h> // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
#include <hd44780.h> // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
hd44780_I2Cexp lcd2; // declare lcd object: auto locate & auto config expander chip
/////////////////////////////////////////////////////////////////////////////////////
//Defines:
/////////////////////////////////////////////////////////////////////////////////////
//LCD display parameters
const int LCD_COLS = 16;
const int LCD_ROWS = 2;
//General parameters
#define DEBOUNCEHARDNESS 10u
//Macros
//Scale
//0.0001ohm - 156mA
#define SCALE_01 digitalWrite(10, LOW); \
digitalWrite(11, HIGH); \
digitalWrite(12, HIGH); \
pinMode(10, OUTPUT); \
pinMode(11, OUTPUT); \
pinMode(12, OUTPUT)
//0.001ohm - 15.6mA
#define SCALE_1 digitalWrite(11, LOW); \
digitalWrite(10, HIGH); \
digitalWrite(12, HIGH); \
pinMode(10, OUTPUT); \
pinMode(11, OUTPUT); \
pinMode(12, OUTPUT)
//0.01ohm - 1.56mA
#define SCALE_10 digitalWrite(12, LOW); \
digitalWrite(11, HIGH); \
digitalWrite(10, HIGH); \
pinMode(10, OUTPUT); \
pinMode(11, OUTPUT); \
pinMode(12, OUTPUT)
//Arduino builtin LED
#define STATUS_ON digitalWrite(LED_BUILTIN, HIGH); \
pinMode(LED_BUILTIN, OUTPUT)
#define STATUS_OFF digitalWrite(LED_BUILTIN, LOW); \
pinMode(LED_BUILTIN, OUTPUT)
//SCALE pushbutton
#define INIT_SCALE pinMode(7, INPUT) //Config SCALE pushbutton pin
#define IS_SCALE_ON (LOW == digitalRead(7)) //true if ON pushed
//CAL pushbutton
#define INIT_CAL pinMode(6, INPUT) //Config CAL pushbutton pin
#define IS_CAL_ON (LOW == digitalRead(6)) //true if CAL pushed
//MCP3422
#define MCP3422_CH1 0x00
#define MCP3422_CH2 0x01
//#define MCP3422_SR 0x00 //240 SPS (12bit)
//#define MCP3422_SR 0x01 //60 SPS (14bit)
//#define MCP3422_SR 0x02 //15 SPS (16bit)
#define MCP3422_SR 0x03 //3.75 SPS (18bit)
#define MCP3422_GAIN 0x00 //x1
//#define MCP3422_GAIN 0x01 //x2
//#define MCP3422_GAIN 0x02 //x4
//#define MCP3422_GAIN 0x03 //x8
#define MCP3422_CR_STARTONESHOT 0x80 // /RDY bit = 1, /O/C bit = 0
#define MCP3422_CR_READY 0x80 // /RDY bit mask
#define MCP3422_NCH 2u //Number of channels available
#define MCP3422_ADD 0x68 //Slave address
//Messages
const char strHOLD[5] = "HOLD";
const char strRUN[5] = " RUN";
const char strScale0m1[6] = "(0m1)";
const char strScale1m0[6] = "(1m0)";
const char strScale10m[6] = "(10m)";
const char strScaleAuto[7] = "(Auto)";
const char strFullScale[9] = "--------";
//EEPROM Addresses
#define EE_U8MODE 0x0000
#define EE_U8SCALERUN 0x0002
#define EE_U8SCALEHOLD 0x0004
#define EE_U32MEASHOLD 0x0006
#define MODEHOLD 0x50
#define MODERUN 0x05
/////////////////////////////////////////////////////////////////////////////////////
//Constants:
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
//Types:
/////////////////////////////////////////////////////////////////////////////////////
//MCP3422 machine states
enum eMCP3422ReadStates_t
{
eMS_WaitCurrent = 0,
eMS_WaitVoltage = 1
};
/////////////////////////////////////////////////////////////////////////////////////
//Variables:
/////////////////////////////////////////////////////////////////////////////////////
//Display
//Double buffer..
char displayBufferA[2][16] =
{ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
{'0', '0', '.', '0', '0', '0', '0', '~', ' ', ' ', ' ', '(', '0', 'm', '1', ')'},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'R', 'U', 'N'}
};
char displayBufferB[2][16] =
{
{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'}
};
//Display class
//General variables
bool bIsHoldMode = false;
uint8_t u8HoldScale = 0;
uint32_t u32HoldValue = 0;
uint8_t u8CurrentScale = 0; //Current Scale
uint32_t u32CurrentMeasurement = 0; //Last conversion value from MCP3422
bool bMCP3422ValIsPositive = true; //Last conversion sign, in this circuit it's always positive
bool bSCALEPressed = false; //State of On push button
bool bLastSCALEPressed = false; //Last state of On push button, used for flange detection
bool bCALPressed = false; //State of Off push button
bool bLastCALPressed = false; //Last state of Off push button, used for flange detection
uint8_t u8SCALEDebounce = 0; //Debounce counter for On push button
uint8_t u8CALDebounce = 0; //Debounce counter for Off push button
/////////////////////////////////////////////////////////////////////////////////////
//First execution:
/////////////////////////////////////////////////////////////////////////////////////
void setup()
{
if(!eeReadU8(EE_U8SCALERUN , u8CurrentScale))
{
eeStoreU8(EE_U8SCALERUN, 0);
u8CurrentScale = 0;
}
changeScale(u8CurrentScale);
setupDisplay();
Wire.setClock(400000); //Speed for both display and MCP3422
//lcd.setBacklight(HIGH);
//Serial.begin(9600);
}
/////////////////////////////////////////////////////////////////////////////////////
//Loop..
/////////////////////////////////////////////////////////////////////////////////////
void loop()
{
updateInputs(); //Read pushbuttons, update modes and change scale
if(true == eeIsHoldMode())
{//Hold Mode
writeString(1u, 12u, strHOLD); //Update bufferA with the "HOLD" text
eeReadU8(EE_U8SCALEHOLD, u8CurrentScale); //Read the HOLD scale
eeReadU32(EE_U32MEASHOLD, u32CurrentMeasurement); //Read the HOLD measurement
}
else
{//Run Mode
writeString(1u, 12u, strRUN); //Update bufferA with the "RUN" text
eeReadU8(EE_U8SCALERUN, u8CurrentScale); //Read the RUN scale
changeScale(u8CurrentScale); //Set the RUN scale in the current sink
//Read the ADC if a new measurement is available.
if(MCP3422_IsDataAndRead(u32CurrentMeasurement, bMCP3422ValIsPositive))
{//New conversion available
if(false == bMCP3422ValIsPositive)
{
u32CurrentMeasurement = 0;
}
MCP3422_StartConversion(MCP3422_CH1); //Restart conversion
}
}
updateDisplayBuffer(); //Update the rest of BufferA
updateDisplay(); //Write the necessary chars in the display
}
/////////////////////////////////////////////////////////////////////////////////////
//Functions:
/////////////////////////////////////////////////////////////////////////////////////
//Starts a one shot conversion in MCP3422. Gain and sample rate/nbits are giben in defines.
//u8Channel: Chanel of MCP3422 to be read
//return: true if every thing was ok
bool MCP3422_StartConversion(uint8_t u8Channel)
{
bool bIsOK = true;
uint8_t u8ConfigRegister = MCP3422_CR_STARTONESHOT | (MCP3422_SR << 2u) | MCP3422_GAIN; //Set defined parameters
//Check channel range
if ((MCP3422_NCH - 1u) < u8Channel)
{
bIsOK = false;
}
if (true == bIsOK)
{
//Set channel
u8ConfigRegister |= (u8Channel << 5u);
//Write Config Register
//Wire.begin();
Wire.beginTransmission(MCP3422_ADD);
Wire.write(u8ConfigRegister);
if (0 != Wire.endTransmission()) //0 = success in Wire library
{
bIsOK = false;
}
}
return bIsOK;
}
//Checks if the last conversion in MCP3422 is finished, if so updates the output value.
//u32Value: Output variable for ADC value.
//bIsPositive: Output variable for sign: true = positive
//return: true if the conversion was finished and there is data available
bool MCP3422_IsDataAndRead(uint32_t &u32Value, bool &bIsPositive)
{
bool bIsData = false;
uint8_t u8ByteCounter = 0;
uint8_t a4u8RecData[4];
//Wire.begin();
Wire.requestFrom(MCP3422_ADD, 4u);
a4u8RecData[3] |= MCP3422_CR_READY; //Force to NOT ready
for (u8ByteCounter = 0; 4u > u8ByteCounter; u8ByteCounter++)
{
a4u8RecData[u8ByteCounter] = Wire.read();
}
if (MCP3422_CR_READY != (MCP3422_CR_READY & a4u8RecData[3]))
{ //RDY bit = 0 -> conversion finished, data is valid
bIsData = true;
}
if (true == bIsData)
{
//Formatting according to page 22 of datasheet
//Mode 12 bit
#if(0x00 == MCP3422_SR)
if (0x08 == (0x08 & a4u8RecData[0]))
{
bIsPositive = false;
}
else
{
bIsPositive = true;
}
u32Value = ((a4u8RecData[0] & 0x07) << 8u) | a4u8RecData[1];
if (false == bIsPositive)
{
u32Value = ~u32Value - 1; //Two's complement
}
#endif //(0x00 == MCP3422_SR)
//Mode 14 bit
#if(0x01 == MCP3422_SR)
if (0x20 == (0x20 & a4u8RecData[0]))
{
bIsPositive = false;
}
else
{
bIsPositive = true;
}
u32Value = ((a4u8RecData[0] & 0x1F) << 8u) | a4u8RecData[1];
if (false == bIsPositive)
{
u32Value = ~u32Value - 1; //Two's complement
}
#endif //(0x01 == MCP3422_SR)
//Mode 16 bit
#if(0x02 == MCP3422_SR)
if (0x80 == (0x80 & a4u8RecData[0]))
{
bIsPositive = false;
}
else
{
bIsPositive = true;
}
u32Value = ((a4u8RecData[0] & 0x7F) << 8u) | a4u8RecData[1];
if (false == bIsPositive)
{
u32Value = ~u32Value - 1; //Two's complement
}
#endif //(0x02 == MCP3422_SR)
//Mode 18 bit
#if(0x03 == MCP3422_SR)
if (0x02 == (0x02 & a4u8RecData[0]))
{
bIsPositive = false;
}
else
{
bIsPositive = true;
}
u32Value = ((uint32_t)(a4u8RecData[0] & 0x01) << 16u) | ((uint32_t)a4u8RecData[1] << 8u) | a4u8RecData[2];
if (false == bIsPositive)
{
u32Value = ~u32Value - 1; //Two's complement
}
#endif //(0x03 == MCP3422_SR)
}
return bIsData;
}
//Conects the mosfets of the current sink to obtain an output current.
//u8Scae: scale: 0: 156mA, 1: 15.6mA, 2: 1.56mA
void changeScale(uint8_t u8Scale)
{
switch(u8Scale)
{
case 0:
{
SCALE_01;
break;
}
case 1:
{
SCALE_1;
break;
}
case 2:
{
SCALE_10;
break;
}
}
}
//Updates the state and value of pushbuttons, store modes in EEPROM,
void updateInputs(void)
{
uint8_t u8RunScale = 0;
//Init inputs
INIT_SCALE;
INIT_CAL;
//Debouncing of pushbuttons...
//Scale
if (IS_SCALE_ON)
{
if (DEBOUNCEHARDNESS <= u8SCALEDebounce)
{ //DEBOUNCEHARDNESS times consecutively read true
bSCALEPressed = true;
}
else
{
u8SCALEDebounce++;
}
}
else
{
u8SCALEDebounce = 0;
bSCALEPressed = false;
}
//Cal
if (IS_CAL_ON)
{
if (DEBOUNCEHARDNESS <= u8CALDebounce)
{ //DEBOUNCEHARDNESS times consecutively read true
bCALPressed = true;
}
else
{
u8CALDebounce++;
}
}
else
{
u8CALDebounce = 0;
bCALPressed = false;
}
if(bLastSCALEPressed != bSCALEPressed)
{//Flange in Scale
if(true == bSCALEPressed)
{//Scale pushed
if(true == eeIsHoldMode())
{//If the meter was in HOLD mode: Return to RUN
eeSetMode(MODERUN); //bIsHoldMode = false;
}
else
{//If the meter was in RUN mode: Change scale
if(true == eeReadU8(EE_U8SCALERUN , u8RunScale)) //Read the latest scale value
{ //Stored value was OK
u8RunScale++; //Increment 0 - 1 - 2
if(2u < u8RunScale)
{
u8RunScale = 0;
}
}
else
{ //Stored value was Corruped
u8RunScale = 0;
}
eeStoreU8(EE_U8SCALERUN , u8RunScale); //Store the new value of scale
}
}
}
bLastSCALEPressed = bSCALEPressed;
if(bLastCALPressed != bCALPressed)
{//Flange in Cal "HOLD button"
if(true == bCALPressed)
{//Hold pressed
if(false == eeIsHoldMode())
{//If the meter was in RUN mode: Put in hold mode
if(false == eeReadU8(EE_U8SCALERUN , u8RunScale))
{
eeStoreU8(EE_U8SCALERUN , 0);
}
eeStoreU8(EE_U8SCALEHOLD, u8RunScale);
eeStoreU32(EE_U32MEASHOLD, u32CurrentMeasurement);
eeSetMode(MODEHOLD); //bIsHoldMode = true;
}
}
}
bLastCALPressed = bCALPressed;
}
//Setup LCD.
void setupDisplay(void)
{
int status;
status = lcd2.begin(LCD_COLS, LCD_ROWS);
if(status) // non zero status means it was unsuccesful
{
// hd44780 has a fatalError() routine that blinks an led if possible
// begin() failed so blink error code using the onboard LED if possible
hd44780::fatalError(status); // does not return
}
}
//Modifies displayBufferA with current measurement and mode
void updateDisplayBuffer(void)
{
if(129999 >= u32CurrentMeasurement)
{
writeNNNNNN(u8CurrentScale,u32CurrentMeasurement, 0u, 0u);
displayBufferA[0u][7u] = char(0xF4);
}
else
{
writeString(0u, 0u, strFullScale);
}
switch(u8CurrentScale)
{
case 0:
{
writeString(0u, 11u, strScale0m1);
break;
}
case 1:
{
writeString(0u, 11u, strScale1m0);
break;
}
case 2:
{
writeString(0u, 11u, strScale10m);
break;
}
}
}
//Browses displayBufferA. If any character is different in displayBufferA than displayBufferB
//writes it to displayBufferB and the LCD. Updates the possition of the cursor when neccesBary.
void updateDisplay(void)
{
uint8_t u8Rows = 0;
uint8_t u8Columns = 0;
bool bMustSetCuror = true;
for (u8Rows = 0; u8Rows < 2; u8Rows++)
{
for (u8Columns = 0; u8Columns < 16; u8Columns++)
{
//Enters here for each character in displayBufferA
if (displayBufferA[u8Rows][u8Columns] != displayBufferB[u8Rows][u8Columns])
{
//A new character must be written
if (true == bMustSetCuror)
{
//Cursor must be updated because last character was not written
lcd2.setCursor(u8Columns, u8Rows);
}
bMustSetCuror = false;
lcd2.print(displayBufferA[u8Rows][u8Columns]);
displayBufferB[u8Rows][u8Columns] = displayBufferA[u8Rows][u8Columns];
}
else
{
//No character to be written
bMustSetCuror = true;
}
}
//Update cursor in new row
bMustSetCuror = true;
}
}
//Writes a string starting at the specified position.
//u8Line: Line.
//u8Column: Column.
//strText: text to write must be a c string with null terminator.
void writeString(uint8_t u8Line, uint8_t u8Column, const char* strText)
{
uint8_t u8Index = 0;
while((strText[u8Index] != '\0') && (16 > (u8Column + u8Index)))
{
displayBufferA[u8Line][u8Column + u8Index] = strText[u8Index];
u8Index++;
}
}
//Writes a NNNNNN fixed dot number in displayBufferA. The dot is located depending on the scale
//in NN.NNNN if scale == 0, in NNN.NNN if scale == 1, in NNNN.NN if scale = 2.
//u8Scale: current scale.
//u32Value: Number to be written, 0 = 000000 to 999999 = 999999.
//u8Line: Start possition line in displayBufferA.
//u8Column: Start possition column in displayBufferA.
void writeNNNNNN(uint8_t u8Scale, uint32_t u32Value, uint8_t u8Line, uint8_t u8Column)
{
uint8_t u8tmp;
//Limits
if(999999u < u32Value)
{
u32Value = 999999u;
}
if(u8Scale > 2u)
{
u8Scale = 2u;
}
displayBufferA[u8Line][u8Column + 6u] = (u32Value % 10) + 0x30; //6th digit
u8tmp = 6u;
do
{
u8tmp--;
if((u8Scale + 2u) == u8tmp)
{
displayBufferA[u8Line][u8Column + u8tmp] = '.'; //Dot
}
else
{
u32Value /= 10u;
displayBufferA[u8Line][u8Column + u8tmp] = (u32Value % 10) + 0x30; //next digit
}
}
while(u8tmp > 0);
}
//Stores a byte in EEPROM and its complementary value in the next position
//eeaddr: EEPROM address
//u8Value: Value to store
void eeStoreU8(int eeaddr, uint8_t u8Value)
{
EEPROM.write(eeaddr, u8Value);
EEPROM.write(eeaddr + 1u, ~u8Value);
}
//Reads a byte from EEPROM and checks if the next byte is the complementary
//eeaddr: EEPROM address
//u8Value: Read value, by reference.
//return: True if the next position in EEPROM had the complementary value
bool eeReadU8(int eeaddr, uint8_t &u8Value)
{
uint8_t u8CheckValue = 0;
u8Value = EEPROM.read(eeaddr);
u8CheckValue = EEPROM.read(eeaddr + 1u);
u8CheckValue = ~u8CheckValue;
return u8Value == u8CheckValue; //True if checksum was ok
}
//Stores a uint32_t in EEPROM and its complementary value in the next position
//eeaddr: EEPROM address
//u32Value: Value to store
void eeStoreU32(int eeaddr, uint32_t u32Value)
{
EEPROM.put(eeaddr, u32Value);
EEPROM.put(eeaddr + 4u, ~u32Value);
}
//Reads a uint32_t from EEPROM and checks if the next uint32_t is the complementary
//eeaddr: EEPROM address
//u32Value: Read value, by reference.
//return: True if the next position in EEPROM had the complementary value
bool eeReadU32(int eeaddr, uint32_t &u32Value)
{
uint8_t u32CheckValue = 0;
EEPROM.get(eeaddr, u32Value);
EEPROM.get(eeaddr + 4u, u32CheckValue);
u32CheckValue = ~u32CheckValue;
return u32Value == u32CheckValue; //True if checksum was ok
}
//Return true if the mode stored in EEPROM is HOLD, if the mode
//position is corrupted, puts the EEPROM mode in RUN.
bool eeIsHoldMode(void)
{
bool bRet = false;
uint8_t u8Mode;
if(eeReadU8(EE_U8MODE, u8Mode))
{
if(MODEHOLD == u8Mode)
{
bRet = true;
}
}
else
{
eeStoreU8(EE_U8MODE, MODERUN);
}
return bRet;
}
//Sets the mode
//u8Mode: Mode RUN: u8Mode = MODERUN, Mode HOLD: u8Mode = MODEHOLD
void eeSetMode(uint8_t u8Mode)
{
eeStoreU8(EE_U8MODE, u8Mode);
}
//EOF