From 646936bca935b27a650aa81414aeca51ea9a2c2e Mon Sep 17 00:00:00 2001 From: SergioArrighi Date: Sat, 20 Apr 2024 13:59:24 +0200 Subject: [PATCH] initial --- .gitignore | 6 + README.md | 24 ++++ include/README | 39 +++++ lib/README | 46 ++++++ platformio.ini | 15 ++ src/i2cscanner.cpp | 63 ++++++++ src/main.cpp | 348 +++++++++++++++++++++++++++++++++++++++++++++ src/other-main.cpp | 118 +++++++++++++++ test/README | 11 ++ 9 files changed, 670 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 include/README create mode 100644 lib/README create mode 100644 platformio.ini create mode 100644 src/i2cscanner.cpp create mode 100644 src/main.cpp create mode 100644 src/other-main.cpp create mode 100644 test/README diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..71b08af --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.pio +.vscode +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/README.md b/README.md new file mode 100644 index 0000000..53e7dcb --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +ACS71020 default settings +qvo_fine: 15 +sns_fine: 143 +crs_sns: 0 +iavgselen: 0 +rms_avg_1: 0 +rms_avg_2: 0 +pacc_trim: 0 +ichan_del_en: 0 +chan_del_sel: 16 +fault: 255 +fitdly: 0 +halfcycle_en: 0 +squarewave_en: 0 +vevent_cycs: 0 +vadc_rate_set: 0 +overvreg: 0 +undervreg: 0 +delaycnt_sel: 0 + +0x1B +00000000001000001000111000001111 +0x00 0x20 0x8E 0x0F +0x208E0F \ No newline at end of file diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..2593a33 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..41c1a12 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,15 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32dev] +platform = espressif32 +board = esp32dev +monitor_speed = 115200 +framework = arduino diff --git a/src/i2cscanner.cpp b/src/i2cscanner.cpp new file mode 100644 index 0000000..50fb4de --- /dev/null +++ b/src/i2cscanner.cpp @@ -0,0 +1,63 @@ + +// ESP32 I2C Scanner +// Based on code of Nick Gammon http://www.gammon.com.au/forum/?id=10896 +// ESP32 DevKit - Arduino IDE 1.8.5 +// Device tested PCF8574 - Use pullup resistors 3K3 ohms ! +// PCF8574 Default Freq 100 KHz +/* +#include +#include + +// Set I2C bus to use: Wire, Wire1, etc. +#define WIRE Wire + +void setup() { + WIRE.begin(); + + Serial.begin(115200); + while (!Serial) + delay(10); + Serial.println("\nI2C Scanner"); +} + + +void loop() { + byte error, address; + int nDevices; + + Serial.println("Scanning..."); + + nDevices = 0; + for(address = 1; address < 127; address++ ) + { + // The i2c_scanner uses the return value of + // the Write.endTransmisstion to see if + // a device did acknowledge to the address. + WIRE.beginTransmission(address); + error = WIRE.endTransmission(); + + if (error == 0) + { + Serial.print("I2C device found at address 0x"); + if (address<16) + Serial.print("0"); + Serial.print(address,HEX); + Serial.println(" !"); + + nDevices++; + } + else if (error==4) + { + Serial.print("Unknown error at address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found\n"); + else + Serial.println("done\n"); + + delay(5000); // wait 5 seconds for next scan +}*/ \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..183c42d --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,348 @@ + +// ESP32 I2C Scanner +// Based on code of Nick Gammon http://www.gammon.com.au/forum/?id=10896 +// ESP32 DevKit - Arduino IDE 1.8.5 +// Device tested PCF8574 - Use pullup resistors 3K3 ohms ! +// PCF8574 Default Freq 100 KHz + +#include +#include +#include + +#define kNOERROR 0 +#define kREADERROR 1 +#define kWRITEERROR 2 + +const uint32_t WRITE = 0x00; +const uint32_t READ = 0x80; +const uint32_t COMMAND_MASK = 0x80; +const uint32_t ADDRESS_MASK = 0x7F; + +unsigned long nextTime; + +byte acs_address; + +float qToFloat(int32_t fixedPointValue, int fractionalBits) +{ + // Cast to float and shift down by the number of fractional bits + return static_cast(fixedPointValue) / (1 << fractionalBits); +} + +uint16_t Read(uint8_t address, uint32_t &value) +{ + uint16_t results = kNOERROR; + Wire.beginTransmission(acs_address); + Wire.write(address); + results = Wire.endTransmission(); + if (results == kNOERROR) + { + Wire.requestFrom(acs_address, 4u); + value = Wire.read(); // receive a byte as character + value |= Wire.read() << 8; // receive a byte as character + value |= Wire.read() << 16; // receive a byte as character + value |= Wire.read() << 24; // receive a byte as character + } + else + { + Serial.println("Error"); + } + return results; +} + +uint16_t Write(uint8_t address, uint32_t value) +{ + uint16_t results = kNOERROR; + Wire.beginTransmission(acs_address); + // Send the address then the value (least significant byte first) + Wire.write(address); + Wire.write(value); + Wire.write(value >> 8); + Wire.write(value >> 16); + Wire.write(value >> 24); + results = Wire.endTransmission(); + + if (address < 0x10) + { + delay(30); // If writing to EEPROM delay 30 ms + } + return results; +} + +void setup() +{ + Serial.begin(115200); + // Initialize serial + // Turn on the pullup so the determination of communication protocol can be made. + // pinMode(ProtocolSelectPin, INPUT_PULLUP); + // delay(50); // Wait for the pullup to take affect + // UseI2C = (digitalRead(ProtocolSelectPin) == HIGH); + // Initialize I2C + Wire.begin(); + Wire.setClock(400000); + + while (!Serial) + ; + Serial.println("Using I2C version of ACS71020"); + nextTime = millis(); + + byte error; + int nDevices; + + Serial.println("Scanning..."); + + nDevices = 0; + for (acs_address = 1; acs_address < 127; acs_address++) + { + // The i2c_scanner uses the return value of + // the Write.endTransmisstion to see if + // a device did acknowledge to the address. + Wire.beginTransmission(acs_address); + error = Wire.endTransmission(); + + if (error == 0) + { + Serial.print("I2C device found at address 0x"); + if (acs_address < 16) + Serial.print("0"); + Serial.print(acs_address, HEX); + Serial.println(" !"); + + nDevices++; + break; + } + else if (error == 4) + { + Serial.print("Unknown error at address 0x"); + if (acs_address < 16) + Serial.print("0"); + Serial.println(acs_address, HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found\n"); + else + Serial.println("done\n"); + + Write(0x2F, 0x4F70656E); // Unlock device + //Write(0x30, 0x00000001); + // If the Arduino has built in USB, keep the next line + // in to wait for the Serial to initialize + + Write(0x1B, 0x11E0F); + delay(100); + uint32_t tuning; + uint32_t qvo_fine; + uint32_t sns_fine; + uint32_t crs_sns; + uint32_t iavgselen; + uint32_t average; + uint32_t rms_avg_1; + uint32_t rms_avg_2; + uint32_t trim; + uint32_t pacc_trim; + uint32_t ichan_del_en; + uint32_t chan_del_sel; + uint32_t fault; + uint32_t fitdly; + uint32_t halfcycle_en; + uint32_t squarewave_en; + uint32_t events; + uint32_t vevent_cycs; + uint32_t vadc_rate_set; + uint32_t overvreg; + uint32_t undervreg; + uint32_t delaycnt_sel; + Read(0x1B, tuning); + qvo_fine = tuning & 0x1FF; + Serial.print("qvo_fine: "); + Serial.println(qvo_fine); + sns_fine = (tuning >> 9) & 0x1FF; + Serial.print("sns_fine: "); + Serial.println(sns_fine); + crs_sns = (tuning >> 18) & 0x1F; + Serial.print("crs_sns: "); + Serial.println(crs_sns); + iavgselen = (tuning >> 21) & 0x1; + Serial.print("iavgselen: "); + Serial.println(iavgselen); + Read(0x0C, average); + rms_avg_1 = average & 0x7F; + Serial.print("rms_avg_1: "); + Serial.println(rms_avg_1); + rms_avg_2 = (average >> 7) & 0x3FF; + Serial.print("rms_avg_2: "); + Serial.println(rms_avg_2); + Read(0x0D, trim); + pacc_trim = trim & 0x7F; + Serial.print("pacc_trim: "); + Serial.println(pacc_trim); + ichan_del_en = (trim >> 7) & 0x1; + Serial.print("ichan_del_en: "); + Serial.println(ichan_del_en); + chan_del_sel = (trim >> 9) & 0x1F; + Serial.print("chan_del_sel: "); + Serial.println(chan_del_sel); + fault = (trim >> 13) & 0xFF; + Serial.print("fault: "); + Serial.println(fault); + fitdly = (trim >> 21) & 0x1F; + Serial.print("fitdly: "); + Serial.println(fitdly); + halfcycle_en = (trim >> 24) & 0x1; + Serial.print("halfcycle_en: "); + Serial.println(halfcycle_en); + squarewave_en = (trim >> 25) & 0x1; + Serial.print("squarewave_en: "); + Serial.println(squarewave_en); + vevent_cycs = events & 0x1F; + Serial.print("vevent_cycs: "); + Serial.println(vevent_cycs); + vadc_rate_set = (events >> 5) & 0x1; + Serial.print("vadc_rate_set: "); + Serial.println(vadc_rate_set); + overvreg = (events >> 8) & 0x3F; + Serial.print("overvreg: "); + Serial.println(overvreg); + undervreg = (events >> 14) & 0x3F; + Serial.print("undervreg: "); + Serial.println(undervreg); + delaycnt_sel = (events >> 20) & 0x1; + Serial.print("delaycnt_sel: "); + Serial.println(delaycnt_sel); + delay(5000); + //teleplot.update("vrms", 10); +} + +void loop() +{ + uint32_t vrms_irms; + uint32_t vrms; + uint32_t irms; + uint32_t pactive; + uint32_t paparent; + uint32_t pimag; + uint32_t pfactor; + uint32_t numptsout; + uint32_t vrmsavgonesec_irmsavgonesec; + uint32_t vrmsavgonesec; + uint32_t irmsavgonesec; + uint32_t vrmsavgonemin_irmsavgonemin; + uint32_t vrmsavgonemin; + uint32_t irmsavgonemin; + uint32_t pactavgonesec; + uint32_t pactavgonemin; + uint32_t vcodes; + uint32_t icodes; + uint32_t pinstant; + uint32_t flags; + Read(0x20, vrms_irms); + Read(0x21, pactive); + Read(0x22, paparent); + Read(0x23, pimag); + Read(0x24, pfactor); + Read(0x25, numptsout); + Read(0x26, vrmsavgonesec_irmsavgonesec); + Read(0x27, vrmsavgonemin_irmsavgonemin); + Read(0x28, pactavgonesec); + Read(0x29, pactavgonemin); + Read(0x2A, vcodes); + Read(0x2B, icodes); + Read(0x2C, pinstant); + Read(0x2D, flags); + //Serial.println(vrms_irms); + std::bitset<32> bits(vrms_irms); + //Serial.println(bits.to_string().c_str()); + vrms = vrms_irms & 0x7FFF; + Serial.print(">vrms:"); + Serial.println(vrms); + irms = (vrms_irms >> 16) & 0x7FFF; + Serial.print(">irms:"); + Serial.println(irms); + /* + Serial.printf("vrms = %ul\n", vrms); + irms = (vrms_irms >> 16) & 0x7FFF; + Serial.printf("irms = %ul\n", irms); + pactive = pactive & 0x1FFFF; + Serial.printf("pactive = %dl\n", pactive); + paparent = paparent & 0xFFFF; + Serial.printf("paparent = %ul\n", paparent); + pimag = pimag & 0x1FFFF; + Serial.printf("pimag = %ul\n", pimag); + pfactor = pfactor & 0x7FF; + Serial.printf("pfactor = %dl\n", pfactor); + numptsout = numptsout & 0x1FF; + Serial.printf("numptsout = %ul\n", numptsout); + vrmsavgonesec = vrmsavgonesec_irmsavgonesec & 0x7FFF; + Serial.printf("vrmsavgonesec = %ul\n", vrmsavgonesec); + irmsavgonesec = (vrmsavgonesec_irmsavgonesec >> 16) & 0x7FFF; + Serial.printf("irmsavgonesec = %ul\n", irmsavgonesec); + */ + vrmsavgonesec = vrmsavgonesec_irmsavgonesec & 0x7FFF; + Serial.print(">vrmsavgonesec:"); + Serial.println(vrmsavgonesec); + irmsavgonesec = (vrmsavgonesec_irmsavgonesec >> 16) & 0x7FFF; + Serial.print(">irmsavgonesec:"); + Serial.println(irmsavgonesec); + + /* + vrmsavgonemin = vrmsavgonemin_irmsavgonemin & 0x7FFF; + Serial.print(">vrmsavgonemin:"); + Serial.println(vrmsavgonemin); + irmsavgonemin = (vrmsavgonemin_irmsavgonemin >> 16) & 0x7FFF; + Serial.print(">irmsavgonemin:"); + Serial.println(irmsavgonemin); + */ + /* + Serial.printf("vrmsavgonemin = %ul\n", vrmsavgonemin); + float testa = qToFloat(vrmsavgonemin, 15); + Serial.println(testa); + irmsavgonemin = (vrmsavgonemin_irmsavgonemin >> 16) & 0x7FFF; + Serial.printf("irmsavgonemin = %ul\n", irmsavgonemin); + pactavgonesec = pactavgonesec & 0x1FFFF; + Serial.printf("pactavgonesec = %ul\n", pactavgonesec); + */ + //pactavgonemin = pactavgonemin & 0x1FFFF; + //Serial.print(">pactavgonemin:"); + //Serial.println(pactavgonemin); + /* + Serial.printf("pactavgonemin = %ul\n", pactavgonemin); + */ + //vcodes = vcodes & 0x1FFFF; + //Serial.print(">vcodes:"); + //Serial.println(vcodes); + /* + Serial.printf("vcodes = %ul\n", vcodes); + std::bitset<32> bitsv(vcodes); + Serial.println(bitsv.to_string().c_str()); + */ + //icodes = icodes & 0x1FFFF; + //Serial.print(">icodes:"); + //Serial.println(icodes); + /* + icodes = icodes & 0x1FFFF; + Serial.printf("icodes = %ul\n", icodes); + Serial.printf("pinstant = %ul\n", pinstant); + Serial.print("pospf = "); + Serial.println((flags >> 6) & 0x1); + Serial.print("posangle = "); + Serial.println((flags >> 5) & 0x1); + Serial.print("undervoltage = "); + Serial.println((flags >> 4) & 0x1); + */ + //Serial.print(">undervoltage:"); + //Serial.println((flags >> 4) & 0x1); + /* + Serial.print("overvoltage = "); + Serial.println((flags >> 3) & 0x1); + Serial.print("faultlatched = "); + Serial.println((flags >> 2) & 0x1); + Serial.print("faultout = "); + Serial.println((flags >> 1) & 0x1); + Serial.print("vzerocrossout = "); + Serial.println((flags >> 0) & 0x1); + Serial.println(); + */ + //Serial.print(">vzerocrossout:"); + //Serial.println((flags >> 0) & 0x1); + delay(5); // wait 5 seconds for next scan +} \ No newline at end of file diff --git a/src/other-main.cpp b/src/other-main.cpp new file mode 100644 index 0000000..4428943 --- /dev/null +++ b/src/other-main.cpp @@ -0,0 +1,118 @@ + +// ESP32 I2C Scanner +// Based on code of Nick Gammon http://www.gammon.com.au/forum/?id=10896 +// ESP32 DevKit - Arduino IDE 1.8.5 +// Device tested PCF8574 - Use pullup resistors 3K3 ohms ! +// PCF8574 Default Freq 100 KHz +/* +#include +#include +#include + +#define kNOERROR 0 +#define kREADERROR 1 +#define kWRITEERROR 2 + +const uint32_t WRITE = 0x00; +const uint32_t READ = 0x80; +const uint32_t COMMAND_MASK = 0x80; +const uint32_t ADDRESS_MASK = 0x7F; + +unsigned long nextTime; + +float qToFloat(int32_t fixedPointValue, int fractionalBits) { + // Cast to float and shift down by the number of fractional bits + return static_cast(fixedPointValue) / (1 << fractionalBits); +} + + +uint16_t Read(uint8_t address, uint32_t &value) +{ + uint16_t results = kNOERROR; + Wire.beginTransmission(0x66); + Wire.write(address); + results = Wire.endTransmission(); + if (results == kNOERROR) + { + Wire.requestFrom(0x66, 4u); + value = Wire.read(); // receive a byte as character + } else { + Serial.println("Error"); + } + return results; +} + +uint16_t Write(uint8_t address, uint32_t value) +{ + uint16_t results = kNOERROR; + Wire.beginTransmission(0x66); + // Send the address then the value (least significant byte first) + Wire.write(address); + Wire.write(value); + Wire.write(value >> 8); + Wire.write(value >> 16); + Wire.write(value >> 24); + results = Wire.endTransmission(); + + if (address < 0x10) + { + delay(30); // If writing to EEPROM delay 30 ms + } + return results; +} + +void setup() +{ + Serial.begin(115200); +// Initialize serial + // Turn on the pullup so the determination of communication protocol can be made. + //pinMode(ProtocolSelectPin, INPUT_PULLUP); + //delay(50); // Wait for the pullup to take affect + //UseI2C = (digitalRead(ProtocolSelectPin) == HIGH); + // Initialize I2C + Wire.begin(); + Wire.setClock(400000); + Write(0x2F, 0x4F70656E); // Unlock device + // If the Arduino has built in USB, keep the next line + // in to wait for the Serial to initialize + while (!Serial); + Serial.println("Using I2C version of ACS71020"); + nextTime = millis(); +} + +void loop() +{ + uint16_t Irms; + uint16_t Vrms; + byte buff[4]; + Wire.beginTransmission(0x66); + Wire.write( 0x20); + Wire.endTransmission(); + Wire.requestFrom(0x66, 4); + int nrrr = 0; + while (Wire.available()) { // slave may send less than requested + char c = Wire.read(); // receive a byte as character + buff[nrrr++] = c; + } + + Vrms = (buff[1] << 8) + buff[0]; + bitClear(Vrms, 15); + Irms = (buff[3] << 8) + buff[2]; + bitClear(Irms, 15); + + float testVRM = ((float)Vrms) * 0.00003051757; //or /32768.0 + float testVRMMM = qToFloat(Vrms, 15); + //Serial.println(testVRM); + + + // both give same value + testVRMMM = testVRMMM *325; + Serial.println(testVRMMM); + + float testIRM = qToFloat(Irms, 14); // ((float)Irms) * 0.00006103515; + + float testIRMS = ((float)Irms) * 0.00006103515; //or /32768.0 + testIRMS = testIRMS * 30; // wait 5 seconds for next scan + delay(500); +} +*/ \ No newline at end of file diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html