Skip to content

Commit

Permalink
Arduino ci (#3)
Browse files Browse the repository at this point in the history
* add arduino-ci
* add unittest - not 100% OK, issue made
* improve readme.md
  • Loading branch information
RobTillaart authored Dec 6, 2020
1 parent 5da7057 commit 8c44680
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 49 deletions.
7 changes: 7 additions & 0 deletions .arduino-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
- leonardo
- due
- zero
13 changes: 13 additions & 0 deletions .github/workflows/arduino_test_runner.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
name: Arduino CI

on: [push, pull_request]

jobs:
arduino_ci:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: Arduino-CI/action@master
# Arduino-CI/[email protected]
82 changes: 42 additions & 40 deletions ACS712.cpp
Original file line number Diff line number Diff line change
@@ -1,66 +1,68 @@
//
// FILE: ACS712.cpp
// AUTHOR: Rob Tillaart, Pete Thompson
// VERSION: 0.2.0
// VERSION: 0.2.1
// DATE: 2020-08-02
// PURPOSE: ACS712 library - current measurement
//
// HISTORY:
// 0.1.0 2020-03-17 initial version
// 0.1.1 2020-03-18 first release version
// 0.1.2 2020-03-21 automatic formfactor test
// 0.1.2 2020-03-21 automatic formfactor test
// 0.1.3 2020-05-27 fix library.json
// 0.1.4 2020-08-02 Allow for faster processors
// 0.2.0 2020-08-02 Add autoMidPoint
// 0.2.1 2020-12-06 Add arduino-CI + readme + unittest + refactor

#include "ACS712.h"

ACS712::ACS712(uint8_t analogPin, float volts, uint16_t maxADC, uint8_t mVperA)
{
_pin = analogPin;
// 1x 1000 for V -> mV
_mVpstep = 1000.0 * volts / maxADC;
_mVperAmpere = mVperA;
_formFactor = 0.70710678119; // 0.5 * sqrt(2); TODO: should be smaller in practice 0.5 ?
_midPoint = maxADC / 2;
_noisemV = 21; // Noise is 21mV according to datasheet
_pin = analogPin;
_mVpstep = 1000.0 * volts / maxADC; // 1x 1000 for V -> mV
_mVperAmpere = mVperA;
_formFactor = 0.70710678119; // 0.5 * sqrt(2); TODO: should be smaller in practice 0.5 ?
_midPoint = maxADC / 2;
_noisemV = 21; // Noise is 21mV according to datasheet
}

int ACS712::mA_AC(uint8_t freq)
{
uint32_t start = micros();
uint16_t period = ((freq == 60) ? 16670 : 20000);
uint16_t samples = 0;
uint16_t zeros = 0;
int _min, _max;
_min = _max = analogRead(_pin);
while (micros() - start < period) // UNO ~180 samples...
{
samples++;
int val = analogRead(_pin);
if (val < _min) _min = val;
if (val > _max) _max = val;
if (abs(val - _midPoint) <= (_noisemV/_mVpstep)) zeros++;
}
int p2p = (_max - _min);
uint32_t start = micros();
uint16_t period = ((freq == 60) ? 16670 : 20000);
uint16_t samples = 0;
uint16_t zeros = 0;

int _min, _max;
_min = _max = analogRead(_pin);

while (micros() - start < period) // UNO ~180 samples...
{
samples++;
int val = analogRead(_pin);
if (val < _min) _min = val;
if (val > _max) _max = val;
if (abs(val - _midPoint) <= (_noisemV/_mVpstep)) zeros++;
}
int point2point = (_max - _min);

// automatic determine _formFactor / crest factor
float D = 0;
float FF = 0;
if (zeros > samples * 0.025)
{
D = 1.0 - (1.0 * zeros) / samples; // % SAMPLES NONE ZERO
FF = sqrt(D) * 0.5 * sqrt(2); // ASSUME NON ZERO PART ~ SINUS
}
else // # zeros is small => D --> 1 --> sqrt(D) --> 1
{
FF = 0.5 * sqrt(2);
}
_formFactor = FF;
// automatic determine _formFactor / crest factor
float D = 0;
float FF = 0;
if (zeros > samples * 0.025)
{
D = 1.0 - (1.0 * zeros) / samples; // % SAMPLES NONE ZERO
FF = sqrt(D) * 0.5 * sqrt(2); // ASSUME NON ZERO PART ~ SINUS
}
else // # zeros is small => D --> 1 --> sqrt(D) --> 1
{
FF = 0.5 * sqrt(2);
}
_formFactor = FF;

// math could be partially precalculated: C = 1000.0 * 0.5 * _mVpstep / _mVperAmpere;
// rounding?
return 1000.0 * 0.5 * p2p * _mVpstep * _formFactor / _mVperAmpere;
// math could be partially precalculated: C = 1000.0 * 0.5 * _mVpstep / _mVperAmpere;
// rounding?
return 1000.0 * 0.5 * point2point * _mVpstep * _formFactor / _mVperAmpere;
}

int ACS712::mA_DC()
Expand Down
10 changes: 5 additions & 5 deletions ACS712.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// FILE: ACS712.h
// AUTHOR: Rob Tillaart
// VERSION: 0.2.0
// VERSION: 0.2.1
// DATE: 2020-08-02
// PURPOSE: ACS712 library - current measurement
//
Expand All @@ -11,7 +11,7 @@

#include "Arduino.h"

#define ACS712_LIB_VERSION "0.1.3"
#define ACS712_LIB_VERSION "0.2.1"


class ACS712
Expand All @@ -37,7 +37,7 @@ class ACS712
int mA_DC();

// midpoint ADC for DC only
inline void setMidPoint(uint16_t mp) { _midPoint = mp; };
inline void setMidPoint(uint16_t mp) { _midPoint = mp; };
inline uint16_t getMidPoint() { return _midPoint; };
inline void incMidPoint() { _midPoint++; };
inline void decMidPoint() { _midPoint--; };
Expand All @@ -58,8 +58,8 @@ class ACS712

private:
uint8_t _pin;
float _mVpstep; // millivolt per step
float _formFactor; // P2P -> RMS
float _mVpstep; // millivolt per step
float _formFactor; // point2point -> RMS
uint8_t _mVperAmpere;
uint16_t _midPoint;
uint8_t _noisemV;
Expand Down
45 changes: 43 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@

[![Arduino CI](https://github.com/RobTillaart/ACS712/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/ACS712/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/ACS712.svg?maxAge=3600)](https://github.com/RobTillaart/ACS712/releases)

# ACS712

Current Sensor - 5A, 20A, 30A
Expand All @@ -9,8 +14,8 @@ analog output that provides a voltage that is lineair with the current.
The ACS712 library supports only a built in ADC by means of analogRead().
There are 2 core functions:

* **int mA_DC()**
* **int mA_AC()**
- **int mA_DC()**
- **int mA_AC()**

To measure DC current a single analogRead() with some conversion math is sufficient to get
a value. To stabilize the signal analogRead() is called twice.
Expand All @@ -20,10 +25,41 @@ peak to peak value which is converted to the RMS value. To convert the peak2peak
value to RMS one need the so called crest or form factor. This factor depends heavily
on the signal form. For a perfect sinus the value is sqrt(2)/2.

## Interface

#### Base
- **ACS712(analogPin, volts = 5.0, maxADC = 1023, mVperA = 100)** constructor
- **mA_AC(freq = 50)** blocks ~21 ms to sample a whole 50 or 60 Hz period.
- **mA_DC()**

#### Midpoint
- **setMidPoint(mp)** sets midpoint ADC for DC only
- **autoMidPoint(uint8_t freq = 50)** Auto midPoint, assuming zero DC current or any AC current
- **getMidPoint()** read back setting
- **incMidPoint()** manual adjust
- **decMidPoint()** manual adjust

#### Formfactor
Also known as crest factor; affects AC only. Default = 0.5 * sqrt(2) ~ 0.707...
- **setFormFactor(ff)** manually sets formfactor 0.0 .. 1.0
- **getFormFactor()** returns current formFactor

#### Noise
Default = 21 mV.
- **setNoisemV(noisemV)**
- **getNoisemV()**

#### mV per Ampere
Both for AC and DC
- **setmVperAmp(mva)**
- **getmVperAmp()**


## Test

The library is tested with the RobotDyn ACS712 20A breakout and an Arduino UNO.


## Operation

With the constructor the parameters **volts** and **maxADC (steps)** of the ADC are set
Expand All @@ -41,3 +77,8 @@ To callibrate the noise level (used for AC measurements), 2 functions are availa
get and set the noise in mV.

The examples show the basic working of the functions.

## Future
- mA_AC blocks 20 ms so might affect taskscheduling on a ESP32.
This needs to be investigated.
- int point2point(uint8_t freq) function for AC. Is part of mA_AC() allready.
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/ACS712"
},
"version":"0.2.0",
"version":"0.2.1",
"frameworks": "arduino",
"platforms": "*"
}
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=ACS712
version=0.2.0
version=0.2.1
author=Rob Tillaart <[email protected]>, Pete Thompson <[email protected]>
maintainer=Rob Tillaart <[email protected]>
sentence=ACS712 library for Arduino.
Expand Down
126 changes: 126 additions & 0 deletions test/unit_test_001.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
//
// FILE: unit_test_001.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2020-12-06
// PURPOSE: unit tests for the SHT31 temperature and humidity sensor
// https://github.com/RobTillaart/SHT31
// https://www.adafruit.com/product/2857
// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md
//

// supported assertions
// ----------------------------
// assertEqual(expected, actual)
// assertNotEqual(expected, actual)
// assertLess(expected, actual)
// assertMore(expected, actual)
// assertLessOrEqual(expected, actual)
// assertMoreOrEqual(expected, actual)
// assertTrue(actual)
// assertFalse(actual)
// assertNull(actual)

#include <ArduinoUnitTests.h>

#include "Arduino.h"
#include "ACS712.h"

#define A0 0

unittest_setup()
{
}

unittest_teardown()
{
}


unittest(test_mA)
{
ACS712 ACS(A0, 5.0, 1023, 100); // analogPin, volts, maxADC, mVperA

/*
float maac50 = ACS.mA_AC(50);
assertEqual(0, maac50);
float maac60 = ACS.mA_AC(60);
assertEqual(0, maac60);
float madc = ACS.mA_DC();
assertEqual(0, madc);
*/
}

unittest(test_midPoint)
{
ACS712 ACS(A0, 5.0, 1023, 100); // analogPin, volts, maxADC, mVperA

/*
ACS.autoMidPoint(50);
float amp50 = ACS.getMidPoint();
assertEqual(0, amp50);
ACS.autoMidPoint(60);
float amp60 = ACS.getMidPoint();
assertEqual(0, amp60);
*/

ACS.setMidPoint(1000);
float amp = ACS.getMidPoint();
assertEqual(1000, amp);

ACS.incMidPoint();
amp = ACS.getMidPoint();
assertEqual(1001, amp);

ACS.decMidPoint();
amp = ACS.getMidPoint();
assertEqual(1000, amp);
}

unittest(test_formFactor)
{
ACS712 ACS(A0, 5.0, 1023, 100);

// default 0.5 * sqrt(2)
float ff = ACS.getFormFactor();
float eff = 0.5 * sqrt(2);
float delta = abs(eff - ff);
assertMoreOrEqual(0.0001, delta);

ACS.setFormFactor(0.8);
ff = ACS.getFormFactor();
eff = 0.8;
delta = abs(eff - ff);
assertMoreOrEqual(0.0001, delta);
}

unittest(test_Noise)
{
ACS712 ACS(A0, 5.0, 1023, 100);

int nmv = ACS.getNoisemV();
assertEqual(21, nmv); // default value..

ACS.setNoisemV(100);
nmv = ACS.getNoisemV();
assertEqual(100, nmv);
}

unittest(test_mVperAmp)
{
ACS712 ACS(A0, 5.0, 1023, 100);

int mpa = ACS.getmVperAmp();
assertEqual(100, mpa); // default value..

ACS.setmVperAmp(50);
mpa = ACS.getmVperAmp();
assertEqual(50, mpa);
}

unittest_main()

// --------

0 comments on commit 8c44680

Please sign in to comment.