├── .gitignore ├── LICENSE ├── README.md ├── examples ├── calibrate │ └── calibrate.ino └── simple_usage │ └── simple_usage.ino ├── img ├── schematic.png └── wave.png ├── keywords.txt ├── library.json ├── library.properties └── src ├── ZMPT101B.cpp └── ZMPT101B.h /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ruslan Koptiev 4 | Copyright (c) 2019 Abdurraziq Bachmid 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZMPT101B 2 | 3 | An Arduino library to interact with the [ZMPT101B](http://www.zeming-e.com/file/0_2013_10_18_093344.pdf), 4 | an active single phase AC voltage sensor module. 5 | 6 | This library is based on [Ruslan Koptev](https://github.com/rkoptev) ACS712 7 | current sensors library for Arduino . 8 | This library is modified so that it can be used with ZMPT101B voltage sensor 9 | with the same code principle. 10 | 11 | ## Methods 12 | 13 | ### Constructor 14 | 15 | ```c++ 16 | ZMPT101B(uint8_t pin, uint16_t frequency = DEFAULT_FREQUENCY); 17 | ``` 18 | 19 | Constructor has a parameters `pin` for analog input to tell where is connected 20 | and the `frequency` value of the AC voltage that the sensor will measure (by 21 | default 50.0Hz). 22 | 23 | ### Reading RMS Voltage Value 24 | 25 | ```c++ 26 | float getRmsVoltage(uint8_t loopCount = 1) 27 | ``` 28 | 29 | This method allows us to obtain the root mean square (RMS) value of the voltage. 30 | By default this method will only calculate the RMS value of one period wave. If 31 | you want the calculation to be done over several periods you can specify how 32 | many iterations you want. Reading more than once will usually return a more 33 | precise value however, sometimes it will take longer. 34 | 35 | ### Set Sensitivity 36 | 37 | ```c++ 38 | void setSensitivity(float value) 39 | ``` 40 | 41 | This method sets the sensitivity value of the sensor. The Sensitivity is the 42 | ratio of the output voltage sensor (that read by the ADC) to the input voltage 43 | sensor. The default value of sensitivity is 500.0. 44 | 45 | ## Example 46 | 47 | ### Circuit 48 | 49 | ![circuit](/img/schematic.png) 50 | 51 | ⚠️ If you are using a board with a 3.3 Volt system you should connect VCC to 3.3 52 | Volt (eg ESP board family). 53 | 54 | ### Steep 55 | 56 | #### 0. Make sure the output voltage from the sensor is not clipped and distorted 57 | 58 | Connect the sensor to the voltage source you are going to measure. 59 | 60 | Use the following code to observe the waveform from the ZMPT1b sensor output. 61 | 62 | ```c++ 63 | void setup() { 64 | Serial.begin(115200); 65 | } 66 | 67 | void loop() { 68 | Serial.println(analogRead(A0)); 69 | delayMicroseconds(1000); 70 | } 71 | ``` 72 | 73 | Upload code and open serial plotter. 74 | 75 | Rotate the trimpot on the sensor until the output is not clipped, distorted and 76 | safe enough. 77 | 78 | ![Wave](/img/wave.png) 79 | 80 | #### 1. Determine the appropriate sensitivity value 81 | 82 | Open the [calibrate.ino](/examples/calibrate/calibrate.ino) example and change 83 | the `ACTUAL_VOLTAGE` value according to the actual AC voltage value (eg based on 84 | a measurement with a voltmeter or something else). Upload the code then open 85 | serial monitor. Wait until the `sensitivity` value is displayed and then copy it. 86 | 87 | #### 2. Start measurement 88 | 89 | Open the [simple_usage.ino](/examples/simple_usage/simple_usage.ino) example 90 | then change the `SENSITIVITY` value (seventh line) based on the value you got in 91 | the previous process. Upload the code then open the serial monitor to observe 92 | the displayed voltage value. 93 | -------------------------------------------------------------------------------- /examples/calibrate/calibrate.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * This program shows how we can get (estimate) the right sensitivity value for 3 | * the sensor. 4 | * 5 | * This program will swipe from the lowest sensitivity estimate value to the 6 | * highest. The program will stop if the voltage reading result from the sensor 7 | * is within the specified tolerance limit or the sensitivity value has exceeded 8 | * the highest predetermined value (which in this case is considered failed to 9 | * be determined). 10 | */ 11 | 12 | #include 13 | 14 | #define ACTUAL_VOLTAGE 220.0f // Change this based on actual voltage 15 | 16 | #define START_VALUE 0.0f 17 | #define STOP_VALUE 1000.0f 18 | #define STEP_VALUE 0.25f 19 | #define TOLLERANCE 1.0f 20 | 21 | #define MAX_TOLLERANCE_VOLTAGE (ACTUAL_VOLTAGE + TOLLERANCE) 22 | #define MIN_TOLLERANCE_VOLTAGE (ACTUAL_VOLTAGE - TOLLERANCE) 23 | 24 | // ZMPT101B sensor output connected to analog pin A0 25 | // and the voltage source frequency is 50 Hz. 26 | ZMPT101B voltageSensor(A0, 50.0); 27 | 28 | void setup() { 29 | Serial.begin(115200); 30 | Serial.print("The Actual Voltage: "); 31 | Serial.println(ACTUAL_VOLTAGE); 32 | 33 | float senstivityValue = START_VALUE; 34 | voltageSensor.setSensitivity(senstivityValue); 35 | float voltageNow = voltageSensor.getRmsVoltage(); 36 | 37 | Serial.println("Start calculate"); 38 | 39 | while (voltageNow > MAX_TOLLERANCE_VOLTAGE || voltageNow < MIN_TOLLERANCE_VOLTAGE) { 40 | if (senstivityValue < STOP_VALUE) { 41 | senstivityValue += STEP_VALUE; 42 | voltageSensor.setSensitivity(senstivityValue); 43 | voltageNow = voltageSensor.getRmsVoltage(); 44 | Serial.print(senstivityValue); 45 | Serial.print(" => "); 46 | Serial.println(voltageNow); 47 | } else { 48 | Serial.println("Unfortunately the sensitivity value cannot be determined"); 49 | return; 50 | } 51 | } 52 | 53 | Serial.print("Closest voltage within tolerance: "); 54 | Serial.println(voltageNow); 55 | Serial.print("Sensitivity Value: "); 56 | Serial.println(senstivityValue, 10); 57 | } 58 | 59 | void loop() {} 60 | -------------------------------------------------------------------------------- /examples/simple_usage/simple_usage.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * This program shows you how to use the basics of this library. 3 | */ 4 | 5 | #include 6 | 7 | #define SENSITIVITY 500.0f 8 | 9 | // ZMPT101B sensor output connected to analog pin A0 10 | // and the voltage source frequency is 50 Hz. 11 | ZMPT101B voltageSensor(A0, 50.0); 12 | 13 | void setup() { 14 | Serial.begin(115200); 15 | // Change the sensitivity value based on value you got from the calibrate 16 | // example. 17 | voltageSensor.setSensitivity(SENSITIVITY); 18 | } 19 | 20 | void loop() { 21 | // read the voltage and then print via Serial. 22 | float voltage = voltageSensor.getRmsVoltage(); 23 | Serial.println(voltage); 24 | 25 | delay(1000); 26 | } 27 | -------------------------------------------------------------------------------- /img/schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdurraziq/ZMPT101B-arduino/c0559f67f09d58a4645116302d45e45cba5aa8d8/img/schematic.png -------------------------------------------------------------------------------- /img/wave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdurraziq/ZMPT101B-arduino/c0559f67f09d58a4645116302d45e45cba5aa8d8/img/wave.png -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For ZMPT101B 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | ZMPT101B KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | setSensitivity KEYWORD2 16 | getRmsVoltage KEYWORD2 17 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ZMPT101B", 3 | "description": "An Arduino library to interact with the ZMPT101B.", 4 | "keywords": "ZMPT101B, AC, voltage, rms", 5 | "version": "1.0.1", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/Abdurraziq/ZMPT101B-arduino" 9 | }, 10 | "platforms": ["atmelavr", "espressif8266", "espressif32"] 11 | } 12 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=ZMPT101B 2 | version=1.0.1 3 | author=Abdurraiq Bachmid 4 | maintainer=Abdurraiq Bachmid 5 | sentence=Library to interact with the ZMPT101B Voltage sensor. 6 | paragraph=Includes RMS AC Voltage measuring. 7 | category=Sensors 8 | url=https://github.com/Abdurraziq/ZMPT101B-arduino 9 | architectures=* 10 | -------------------------------------------------------------------------------- /src/ZMPT101B.cpp: -------------------------------------------------------------------------------- 1 | #include "ZMPT101B.h" 2 | 3 | /// @brief ZMPT101B constructor 4 | /// @param pin analog pin that ZMPT101B connected to. 5 | /// @param frequency AC system frequency 6 | ZMPT101B::ZMPT101B(uint8_t pin, uint16_t frequency) 7 | { 8 | this->pin = pin; 9 | period = 1000000 / frequency; 10 | pinMode(pin, INPUT); 11 | } 12 | 13 | /// @brief Set sensitivity 14 | /// @param value Sensitivity value 15 | void ZMPT101B::setSensitivity(float value) 16 | { 17 | sensitivity = value; 18 | } 19 | 20 | /// @brief Calculate zero point 21 | /// @return zero / center value 22 | int ZMPT101B::getZeroPoint() 23 | { 24 | uint32_t Vsum = 0; 25 | uint32_t measurements_count = 0; 26 | uint32_t t_start = micros(); 27 | 28 | while (micros() - t_start < period) 29 | { 30 | Vsum += analogRead(pin); 31 | measurements_count++; 32 | } 33 | 34 | return Vsum / measurements_count; 35 | } 36 | 37 | /// @brief Calculate root mean square (RMS) of AC valtage 38 | /// @param loopCount Loop count to calculate 39 | /// @return root mean square (RMS) of AC valtage 40 | float ZMPT101B::getRmsVoltage(uint8_t loopCount) 41 | { 42 | double readingVoltage = 0.0f; 43 | 44 | for (uint8_t i = 0; i < loopCount; i++) 45 | { 46 | int zeroPoint = this->getZeroPoint(); 47 | 48 | int32_t Vnow = 0; 49 | uint32_t Vsum = 0; 50 | uint32_t measurements_count = 0; 51 | uint32_t t_start = micros(); 52 | 53 | while (micros() - t_start < period) 54 | { 55 | Vnow = analogRead(pin) - zeroPoint; 56 | Vsum += (Vnow * Vnow); 57 | measurements_count++; 58 | } 59 | 60 | readingVoltage += sqrt(Vsum / measurements_count) / ADC_SCALE * VREF * sensitivity; 61 | } 62 | 63 | return readingVoltage / loopCount; 64 | } 65 | -------------------------------------------------------------------------------- /src/ZMPT101B.h: -------------------------------------------------------------------------------- 1 | #ifndef ZMPT101B_h 2 | #define ZMPT101B_h 3 | 4 | #include 5 | 6 | #define DEFAULT_FREQUENCY 50.0f 7 | #define DEFAULT_SENSITIVITY 500.0f 8 | 9 | #if defined(AVR) 10 | #define ADC_SCALE 1023.0f 11 | #define VREF 5.0f 12 | #elif defined(ESP8266) 13 | #define ADC_SCALE 1023.0 14 | #define VREF 3.3 15 | #elif defined(ESP32) 16 | #define ADC_SCALE 4095.0 17 | #define VREF 3.3 18 | #endif 19 | 20 | class ZMPT101B 21 | { 22 | public: 23 | ZMPT101B (uint8_t pin, uint16_t frequency = DEFAULT_FREQUENCY); 24 | void setSensitivity(float value); 25 | float getRmsVoltage(uint8_t loopCount = 1); 26 | 27 | private: 28 | uint8_t pin; 29 | uint32_t period; 30 | float sensitivity = DEFAULT_SENSITIVITY; 31 | int getZeroPoint(); 32 | }; 33 | 34 | #endif --------------------------------------------------------------------------------