diff --git a/.codespellrc b/.codespellrc index c47f602..2e6be5c 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,7 +1,7 @@ # See: https://github.com/codespell-project/codespell#using-a-config-file [codespell] # In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: -ignore-words-list = compiletime, +ignore-words-list = compiletime,ro builtin = clear,informal,en-GB_to_en-US check-filenames = check-hidden = diff --git a/.github/workflows/check-arduino.yml b/.github/workflows/check-arduino.yml index f26ccc5..bb160c2 100644 --- a/.github/workflows/check-arduino.yml +++ b/.github/workflows/check-arduino.yml @@ -17,10 +17,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v5 - name: Arduino Lint - uses: arduino/arduino-lint-action@v1 + uses: arduino/arduino-lint-action@v2 with: compliance: specification # TODO: This is only needed for standalone libraries. diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index a324b3e..0889e5c 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -34,16 +34,14 @@ jobs: matrix: board: - # TODO: Add list of boards to compile for here: - fqbn: arduino:mbed_edge:edge_control - # TODO: Define the board's platform dependencies here. - # See: https://github.com/arduino/compile-sketches#platforms platforms: | - name: arduino:mbed_edge + artifact-name-suffix: arduino-mbed_edge-edge_control steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v5 - name: Compile examples uses: arduino/compile-sketches@v1 @@ -68,8 +66,8 @@ jobs: sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} - name: Save sketches report as workflow artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: if-no-files-found: error path: ${{ env.SKETCHES_REPORTS_PATH }} - name: ${{ env.SKETCHES_REPORTS_PATH }} + name: sketches-report-${{ matrix.board.artifact-name-suffix }} diff --git a/.github/workflows/report-size-deltas.yml b/.github/workflows/report-size-deltas.yml index 3eacdf4..0a315f1 100644 --- a/.github/workflows/report-size-deltas.yml +++ b/.github/workflows/report-size-deltas.yml @@ -21,5 +21,5 @@ jobs: - name: Comment size deltas reports to PRs uses: arduino/report-size-deltas@v1 with: - # The name of the workflow artifact created by the sketch compilation workflow - sketches-reports-source: sketches-reports + # Regex matching the names of the workflow artifacts created by the "Compile Examples" workflow + sketches-reports-source: ^sketches-report-.+ diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml index 731a653..55f2391 100644 --- a/.github/workflows/spell-check.yml +++ b/.github/workflows/spell-check.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v5 - name: Spell check uses: codespell-project/actions-codespell@master diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml new file mode 100644 index 0000000..7a9518b --- /dev/null +++ b/.github/workflows/sync-labels.yml @@ -0,0 +1,144 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/sync-labels.md +name: Sync Labels + +# See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows +on: + push: + paths: + - ".github/workflows/sync-labels.ya?ml" + - ".github/label-configuration-files/*.ya?ml" + pull_request: + paths: + - ".github/workflows/sync-labels.ya?ml" + - ".github/label-configuration-files/*.ya?ml" + schedule: + # Run daily at 8 AM UTC to sync with changes to shared label configurations. + - cron: "0 8 * * *" + workflow_dispatch: + repository_dispatch: + +env: + CONFIGURATIONS_FOLDER: .github/label-configuration-files + CONFIGURATIONS_ARTIFACT: label-configuration-files + +jobs: + check: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Download JSON schema for labels configuration file + id: download-schema + uses: carlosperate/download-file-action@v2 + with: + file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/arduino-tooling-gh-label-configuration-schema.json + location: ${{ runner.temp }}/label-configuration-schema + + - name: Install JSON schema validator + run: | + sudo npm install \ + --global \ + ajv-cli \ + ajv-formats + + - name: Validate local labels configuration + run: | + # See: https://github.com/ajv-validator/ajv-cli#readme + ajv validate \ + --all-errors \ + -c ajv-formats \ + -s "${{ steps.download-schema.outputs.file-path }}" \ + -d "${{ env.CONFIGURATIONS_FOLDER }}/*.{yml,yaml}" + + download: + needs: check + runs-on: ubuntu-latest + permissions: {} + + strategy: + matrix: + filename: + # Filenames of the shared configurations to apply to the repository in addition to the local configuration. + # https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/sync-labels + - universal.yml + + steps: + - name: Download + uses: carlosperate/download-file-action@v2 + with: + file-url: https://raw.githubusercontent.com/arduino/tooling-project-assets/main/workflow-templates/assets/sync-labels/${{ matrix.filename }} + + - name: Pass configuration files to next job via workflow artifact + uses: actions/upload-artifact@v4 + with: + path: | + *.yaml + *.yml + if-no-files-found: error + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + + sync: + needs: download + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + + steps: + - name: Set environment variables + run: | + # See: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable + echo "MERGED_CONFIGURATION_PATH=${{ runner.temp }}/labels.yml" >> "$GITHUB_ENV" + + - name: Determine whether to dry run + id: dry-run + if: > + github.event_name == 'pull_request' || + ( + ( + github.event_name == 'push' || + github.event_name == 'workflow_dispatch' + ) && + github.ref != format('refs/heads/{0}', github.event.repository.default_branch) + ) + run: | + # Use of this flag in the github-label-sync command will cause it to only check the validity of the + # configuration. + echo "flag=--dry-run" >> $GITHUB_OUTPUT + + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Download configuration files artifact + uses: actions/download-artifact@v5 + with: + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + path: ${{ env.CONFIGURATIONS_FOLDER }} + + - name: Remove unneeded artifact + uses: geekyeggo/delete-artifact@v5 + with: + name: ${{ env.CONFIGURATIONS_ARTIFACT }} + + - name: Merge label configuration files + run: | + # Merge all configuration files + shopt -s extglob + cat "${{ env.CONFIGURATIONS_FOLDER }}"/*.@(yml|yaml) > "${{ env.MERGED_CONFIGURATION_PATH }}" + + - name: Install github-label-sync + run: sudo npm install --global github-label-sync + + - name: Sync labels + env: + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # See: https://github.com/Financial-Times/github-label-sync + github-label-sync \ + --labels "${{ env.MERGED_CONFIGURATION_PATH }}" \ + ${{ steps.dry-run.outputs.flag }} \ + ${{ github.repository }} diff --git a/README.md b/README.md index 27d1162..00a9970 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ ![Compile Examples](https://github.com/arduino-libraries/Arduino_EdgeControl/actions/workflows/compile-examples.yml/badge.svg) +[![Sync Labels status](https://github.com/arduino-libraries/Arduino_EdgeControl/actions/workflows/sync-labels.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_EdgeControl/actions/workflows/sync-labels.yml) # Arduino_EdgeControl diff --git a/examples/Application/IrrigationSimple/Helpers.cpp b/examples/Application/IrrigationSimple/Helpers.cpp index 534a61b..b426cae 100644 --- a/examples/Application/IrrigationSimple/Helpers.cpp +++ b/examples/Application/IrrigationSimple/Helpers.cpp @@ -3,23 +3,23 @@ /** * Set system and TimeAlarm clock from compile datetime or RTC */ -void setSystemClock(String compileDate, String compileTime) +void setSystemClock(String buildDate, String buildTime) { // Retrieve clock time from compile date... - auto buildTime = compileDateTimeToSystemTime(compileDate, compileTime, true, 2); + auto buildDateTime = buildDateTimeToSystemTime(buildDate, buildTime, true, 2); // ... ore use the one from integrated RTC. auto rtcTime = time(NULL); // Remember to connect at least the CR2032 battery // to keep the RTC running. - auto actualTime = rtcTime > buildTime ? rtcTime : buildTime; + auto actualTime = rtcTime > buildDateTime ? rtcTime : buildDateTime; // Set both system time and the alarms one set_time(actualTime); setTime(actualTime); Serial.print("Compile Date and Time: "); - Serial.println(getLocaltime(buildTime)); + Serial.println(getLocaltime(buildDateTime)); Serial.print("RTC Date and Time: "); Serial.println(getLocaltime(rtcTime)); Serial.print("System Clock: "); diff --git a/examples/Application/IrrigationSimple/TimeHelpers.cpp b/examples/Application/IrrigationSimple/TimeHelpers.cpp index 4451990..9162b6b 100644 --- a/examples/Application/IrrigationSimple/TimeHelpers.cpp +++ b/examples/Application/IrrigationSimple/TimeHelpers.cpp @@ -1,7 +1,7 @@ #include "TimeHelpers.h" // Convert compile time to system time -time_t compileDateTimeToSystemTime(const String date, const String time, bool local_time = true, int tz = 0) +time_t buildDateTimeToSystemTime(const String date, const String time, bool local_time = true, int tz = 0) { char s_month[5]; int year; diff --git a/examples/Application/IrrigationSimple/TimeHelpers.h b/examples/Application/IrrigationSimple/TimeHelpers.h index ec5c3ba..3164616 100644 --- a/examples/Application/IrrigationSimple/TimeHelpers.h +++ b/examples/Application/IrrigationSimple/TimeHelpers.h @@ -4,8 +4,8 @@ #include // Convert compile time to system time -time_t compileDateTimeToSystemTime(const String, const String, bool local_time, int tz); +time_t buildDateTimeToSystemTime(const String, const String, bool local_time, int tz); String getLocaltime(); String getLocaltime(const time_t &build_time); String getLocaltime(const char *fmt, bool local_time, int); -String getLocaltime(const time_t build_time, const char *fmt, bool local_time, int tz); \ No newline at end of file +String getLocaltime(const time_t build_time, const char *fmt, bool local_time, int tz); diff --git a/examples/Application/IrrigationSimpleLCD/Helpers.cpp b/examples/Application/IrrigationSimpleLCD/Helpers.cpp index becd575..2be8900 100644 --- a/examples/Application/IrrigationSimpleLCD/Helpers.cpp +++ b/examples/Application/IrrigationSimpleLCD/Helpers.cpp @@ -3,23 +3,23 @@ /** * Set system and TimeAlarm clock from compile datetime or RTC */ -void setSystemClock(String compileDate, String compileTime) +void setSystemClock(String buildDate, String buildTime) { // Retrieve clock time from compile date... - auto buildTime = compileDateTimeToSystemTime(compileDate, compileTime, true, 2); + auto buildDateTime = buildDateTimeToSystemTime(buildDate, buildTime, true, 2); // ... ore use the one from integrated RTC. auto rtcTime = time(NULL); // Remember to connect at least the CR2032 battery // to keep the RTC running. - auto actualTime = rtcTime > buildTime ? rtcTime : buildTime; + auto actualTime = rtcTime > buildDateTime ? rtcTime : buildDateTime; // Set both system time and the alarms one set_time(actualTime); setTime(actualTime); Serial.print("Compile Date and Time: "); - Serial.println(getLocaltime(buildTime)); + Serial.println(getLocaltime(buildDateTime)); Serial.print("RTC Date and Time: "); Serial.println(getLocaltime(rtcTime)); Serial.print("System Clock: "); diff --git a/examples/Application/IrrigationSimpleLCD/TimeHelpers.cpp b/examples/Application/IrrigationSimpleLCD/TimeHelpers.cpp index 4451990..9162b6b 100644 --- a/examples/Application/IrrigationSimpleLCD/TimeHelpers.cpp +++ b/examples/Application/IrrigationSimpleLCD/TimeHelpers.cpp @@ -1,7 +1,7 @@ #include "TimeHelpers.h" // Convert compile time to system time -time_t compileDateTimeToSystemTime(const String date, const String time, bool local_time = true, int tz = 0) +time_t buildDateTimeToSystemTime(const String date, const String time, bool local_time = true, int tz = 0) { char s_month[5]; int year; diff --git a/examples/Application/IrrigationSimpleLCD/TimeHelpers.h b/examples/Application/IrrigationSimpleLCD/TimeHelpers.h index ec5c3ba..3164616 100644 --- a/examples/Application/IrrigationSimpleLCD/TimeHelpers.h +++ b/examples/Application/IrrigationSimpleLCD/TimeHelpers.h @@ -4,8 +4,8 @@ #include // Convert compile time to system time -time_t compileDateTimeToSystemTime(const String, const String, bool local_time, int tz); +time_t buildDateTimeToSystemTime(const String, const String, bool local_time, int tz); String getLocaltime(); String getLocaltime(const time_t &build_time); String getLocaltime(const char *fmt, bool local_time, int); -String getLocaltime(const time_t build_time, const char *fmt, bool local_time, int tz); \ No newline at end of file +String getLocaltime(const time_t build_time, const char *fmt, bool local_time, int tz); diff --git a/examples/Application/LowPowerDataLogger/Helpers.h b/examples/Application/LowPowerDataLogger/Helpers.h index e47cc8d..5d9db8d 100644 --- a/examples/Application/LowPowerDataLogger/Helpers.h +++ b/examples/Application/LowPowerDataLogger/Helpers.h @@ -58,7 +58,7 @@ int getAverageInputRead(int pin, const size_t loops) } // Convert compile time to system time -time_t compileDateTimeToSystemTime(const String date, const String time, bool local_time = true, int tz = 0) +time_t buildDateTimeToSystemTime(const String date, const String time, bool local_time = true, int tz = 0) { char s_month[5]; int year; @@ -108,22 +108,22 @@ String getLocaltime(const time_t& build_time) /** * Set system clock from compile datetime or RTC */ -void setSystemClock(String compileDate, String compileTime) +void setSystemClock(String buildDate, String buildTime) { // Retrieve clock time from compile date... - auto buildTime = compileDateTimeToSystemTime(compileDate, compileTime, true, 2); + auto buildDateTime = buildDateTimeToSystemTime(buildDate, buildTime, true, 2); // ... ore use the one from integrated RTC. auto rtcTime = time(NULL); // Remember to connect at least the CR2032 battery // to keep the RTC running. - auto actualTime = rtcTime > buildTime ? rtcTime : buildTime; + auto actualTime = rtcTime > buildDateTime ? rtcTime : buildDateTime; // Set both system time set_time(actualTime); DebugSerial.print("Compile Date and Time: "); - DebugSerial.println(getLocaltime(buildTime)); + DebugSerial.println(getLocaltime(buildDateTime)); DebugSerial.print("RTC Date and Time: "); DebugSerial.println(getLocaltime(rtcTime)); DebugSerial.print("System Clock: "); diff --git a/examples/Application/RTCClock/Helpers.h b/examples/Application/RTCClock/Helpers.h index 87392bd..f0ffa10 100644 --- a/examples/Application/RTCClock/Helpers.h +++ b/examples/Application/RTCClock/Helpers.h @@ -6,7 +6,7 @@ // Convert compile time to system time -time_t compileDateTimeToSystemTime(const String date, const String time, bool local_time = true, int tz = 0) +time_t buildDateTimeToSystemTime(const String date, const String time, bool local_time = true, int tz = 0) { char s_month[5]; int year; @@ -56,22 +56,22 @@ String getLocaltime(const time_t& build_time) /** * Set system clock from compile datetime or RTC */ -void setSystemClock(String compileDate, String compileTime) +void setSystemClock(String buildDate, String buildTime) { // Retrieve clock time from compile date... - auto buildTime = compileDateTimeToSystemTime(compileDate, compileTime, true, 2); + auto buildDateTime = buildDateTimeToSystemTime(buildDate, buildTime, true, 2); // ... ore use the one from integrated RTC. auto rtcTime = time(NULL); // Remember to connect at least the CR2032 battery // to keep the RTC running. - auto actualTime = rtcTime > buildTime ? rtcTime : buildTime; + auto actualTime = rtcTime > buildDateTime ? rtcTime : buildDateTime; // Set both system time set_time(actualTime); Serial.print("Compile Date and Time: "); - Serial.println(getLocaltime(buildTime)); + Serial.println(getLocaltime(buildDateTime)); Serial.print("RTC Date and Time: "); Serial.println(getLocaltime(rtcTime)); Serial.print("System Clock: "); diff --git a/examples/Basic/BatterySolarStatus/BatterySolarStatus.ino b/examples/Basic/BatterySolarStatus/BatterySolarStatus.ino index 87c6b27..431bf68 100644 --- a/examples/Basic/BatterySolarStatus/BatterySolarStatus.ino +++ b/examples/Basic/BatterySolarStatus/BatterySolarStatus.ino @@ -20,11 +20,13 @@ void setup() Wire.begin(); delay(500); + Serial.print("I/O Expander initializazion "); - if (!Expander.begin()) { + while (!Expander.begin()) { Serial.println("failed."); Serial.println("Please, be sure to enable gated 3V3 and 5V power rails"); Serial.println("via Power.on(PWR_3V3) and Power.on(PWR_VBAT)."); + delay(500); } Serial.println("succeeded."); @@ -51,4 +53,4 @@ void loop() printNow = millis() + printInterval; } -} \ No newline at end of file +} diff --git a/examples/Basic/IRQCounter/IRQCounter.ino b/examples/Basic/IRQCounter/IRQCounter.ino new file mode 100644 index 0000000..5b607e9 --- /dev/null +++ b/examples/Basic/IRQCounter/IRQCounter.ino @@ -0,0 +1,56 @@ +/* + Testing strategy: alternatively create a short-time connection between + WAKEUP 1-6 and any of the +BAT_ext pins (the row above the WAKEUP ones). + + Check IRQChannelMap for advanced C++ implementation. +*/ + +#include + +volatile int irqCounts[6] { }; + +enum IRQChannelsIndex { + irqChannel1 = 0, + irqChannel2, + irqChannel3, + irqChannel4, + irqChannel5, + irqChannel6 +}; + + +void setup() +{ + EdgeControl.begin(); + + Serial.begin(115200); + + // Wait for Serial Monitor or start after 2.5s + for (const auto timeout = millis() + 2500; millis() < timeout && !Serial; delay(250)); + + // Init IRQ INPUT pins + for (auto pin = IRQ_CH1; pin <= IRQ_CH6; pin++) + pinMode(pin, INPUT); + + // Attach callbacks to IRQ pins + attachInterrupt(digitalPinToInterrupt(IRQ_CH1), []{ irqCounts[irqChannel1]++; }, CHANGE); + attachInterrupt(digitalPinToInterrupt(IRQ_CH2), []{ irqCounts[irqChannel2]++; }, CHANGE); + attachInterrupt(digitalPinToInterrupt(IRQ_CH3), []{ irqCounts[irqChannel3]++; }, CHANGE); + attachInterrupt(digitalPinToInterrupt(IRQ_CH4), []{ irqCounts[irqChannel4]++; }, CHANGE); + attachInterrupt(digitalPinToInterrupt(IRQ_CH5), []{ irqCounts[irqChannel5]++; }, CHANGE); + attachInterrupt(digitalPinToInterrupt(IRQ_CH6), []{ irqCounts[irqChannel6]++; }, CHANGE); + +} + +void loop() +{ + // Check for received IRQ every second. + Serial.println("--------"); + for (unsigned int i = irqChannel1; i <= irqChannel6; i++) { + Serial.print("IRQ Channel: "); + Serial.print(i + 1); + Serial.print(" - "); + Serial.println(irqCounts[i]); + } + delay(1000); +} diff --git a/examples/Basic/IRQCounterMap/IRQCounterMap.ino b/examples/Basic/IRQCounterMap/IRQCounterMap.ino new file mode 100644 index 0000000..232de57 --- /dev/null +++ b/examples/Basic/IRQCounterMap/IRQCounterMap.ino @@ -0,0 +1,73 @@ +/* + Testing strategy: alternatively create a short-time connection between + WAKEUP 1-6 and any of the +BAT_ext pins (the row above the WAKEUP ones). + + Check IRQChannel for a simpler implementation. +*/ + +#include + +#include + +// Use a map to collect IRQ counts +std::map irqCounts { + { IRQ_CH1, 0 }, + { IRQ_CH2, 0 }, + { IRQ_CH3, 0 }, + { IRQ_CH4, 0 }, + { IRQ_CH5, 0 }, + { IRQ_CH6, 0 } +}; + +// Map pin numbers to pin names for pretty printing +std::map irqNames { +#define NE(IRQ) { IRQ, #IRQ } + NE(IRQ_CH1), + NE(IRQ_CH2), + NE(IRQ_CH3), + NE(IRQ_CH4), + NE(IRQ_CH5), + NE(IRQ_CH6), +}; + +void setup() +{ + EdgeControl.begin(); + + Serial.begin(115200); + + // Wait for Serial Monitor or start after 2.5s + for (const auto timeout = millis() + 2500; millis() < timeout && !Serial; delay(250)) + ; + + // Init IRQ pins and attach callbacks + // NOTE: .first holds the channel pin and .second holds the counter + for (const auto& irq : irqCounts) { + // Init pins + pinMode(irq.first, INPUT); + + // Create a type alias helper + using IrqCount = std::pair; + + // Define the IRQ callback as lambda function + // Will receive an entry from the irqCounts map: + auto isr = [](void* arg) { IrqCount * ic = (IrqCount *)arg; (*ic).second++; }; + + // attach the callback passing the current map entry as parameter + attachInterruptParam( + digitalPinToInterrupt(irq.first), isr, RISING, (void*)&irq); + } +} + +void loop() +{ + // Print counters every second. + Serial.println("--------"); + for (const auto& irq : irqCounts) { + Serial.print("IRQ Channel: "); + Serial.print(irqNames[irq.first]); + Serial.print(" - Counts: "); + Serial.println(irq.second); + } + delay(1000); +} diff --git a/examples/Basic/LCD/LCD.ino b/examples/Basic/LCD/LCD.ino index 9ab0756..effca0c 100644 --- a/examples/Basic/LCD/LCD.ino +++ b/examples/Basic/LCD/LCD.ino @@ -45,6 +45,8 @@ byte frownie[8] = { void setup() { + EdgeControl.begin(); + Serial.begin(9600); auto startNow = millis() + 2500; @@ -58,7 +60,16 @@ void setup() Power.on(PWR_VBAT); Wire.begin(); - Expander.begin(); + + delay(500); + + Serial.print("IO Expander initializazion "); + if (!Expander.begin()) { + Serial.println("failed."); + Serial.println("Please, be sure to enable gated 3V3 and 5V power rails"); + Serial.println("via Power.on(PWR_3V3) and Power.on(PWR_VBAT)."); + } + Serial.println("succeeded."); // set up the LCD's number of columns and rows: LCD.begin(16, 2); @@ -69,7 +80,7 @@ void setup() // Print a message to the LCD. LCD.home(); // go home - LCD.print("Hi, Outdoor!"); + LCD.print("Edge Control"); LCD.setCursor(15, 0); LCD.print(char(1)); } diff --git a/examples/Basic/LowPowerButton/LowPowerButton.ino b/examples/Basic/LowPowerButton/LowPowerButton.ino new file mode 100644 index 0000000..0476ba2 --- /dev/null +++ b/examples/Basic/LowPowerButton/LowPowerButton.ino @@ -0,0 +1,169 @@ +/* +* Show usage of POWER_ON pin (J1-2). +* +* Board goes to low power mode as soon as started. +* Pressing a momentary button connected to POWER_ON pin +* will wake up the board for 5 seconds. +* +* Requirements: +* - Connect a momentary button between POWER_ON (J1-2) and GND (J1-9) +* - Connect the PC/Mac to USB and open the Arduino Serial Monitor +* or any serial communication application. +* +*/ + +#include +#include + +constexpr unsigned long printInterval { 250 }; +unsigned long printNow { 0 }; +constexpr unsigned long wakeUpInterval { printInterval * 20 }; +unsigned long sleepNow { 0 }; +volatile bool sleeping { true }; +volatile bool poweredOn { false }; + +void wakeUp() +{ + sleeping = false; + poweredOn = true; +} + +void setup() +{ + EdgeControl.begin(); + Power.on(PWR_3V3); + + Serial.begin(9600); + + auto startNow = millis() + 2500; + while (!Serial && millis() < startNow) + ; + + delay(1000); + Serial.println("Testing Low Power"); + Serial.println("and Power On Button."); + + pinMode(POWER_ON, INPUT); + attachInterrupt(digitalPinToInterrupt(POWER_ON), wakeUp, FALLING); + + sleepNow = millis(); + printNow = millis() + printInterval; + + powerDown(); + +} + +void loop() +{ + if (poweredOn) { + poweredOn = false; + + powerOn(); + + delay(1000); // Wait for Serial Monitor/Serial Communication Application + Serial.println(""); + Serial.println("Woke Up!"); + sleepNow = millis() + wakeUpInterval; + } + + if (millis() > sleepNow && !sleeping) { + // Going to sleep + powerDown(); + sleeping = true; + } + + if (sleeping) + delay(10000); // delay() puts the board in low power mode. + else + if (millis() > printNow) { + Serial.print('.'); + printNow = millis() + printInterval; + } +} + +void powerOn() +{ + // Enable Gated 3V3 to devices and peripherals + Power.on(PWR_3V3); + + // Enable Gated 12V and 5V to output pins, devices and peripherals + Power.on(PWR_VBAT); + + // Enable Gated 12V and 5V to output pins, devices and peripherals + Power.on(PWR_19V); + + // Attach USB + PluggableUSBD().begin(); + + // Enable stdin + mbed::mbed_file_handle(STDIN_FILENO)->enable_input(true); + + // Open Serial and wait for connection + Serial.begin(9600); + while(!Serial); +} + +void powerDown() +{ + Serial.println(); + Serial.println("Powering down"); + + // Disable Gated 3V3 + Power.off(PWR_3V3); + + // Disable Gated 12V and 5V + Power.off(PWR_VBAT); + + // Disable Gated 19V + Power.off(PWR_19V); + + // Close Serial + Serial.end(); + Serial1.end(); + // Disable stdin + mbed::mbed_file_handle(STDIN_FILENO)->enable_input(false); + // Detach USB + PluggableUSBD().deinit(); + // Put pins in threestate + powerDownPins(); +} + +void powerDownPins() +{ + pinMode(I2C_SDA, INPUT_PULLDOWN); + pinMode(I2C_SCL, INPUT_PULLDOWN); + pinMode(I2C_SDA1, INPUT_PULLDOWN); + pinMode(I2C_SCL1, INPUT_PULLDOWN); + + pinMode(VBAT_PROBE, INPUT_PULLDOWN); + + pinMode(CMD_TRIAC_1, INPUT_PULLDOWN); + pinMode(CMD_TRIAC_2, INPUT_PULLDOWN); + pinMode(CMD_TRIAC_3, INPUT_PULLDOWN); + pinMode(CMD_TRIAC_4, INPUT_PULLDOWN); + + pinMode(SENSOR_COMMON, INPUT_PULLDOWN); + pinMode(SENSOR_CALIB, INPUT_PULLDOWN); + pinMode(SENSOR_INPUT_ADC, INPUT_PULLDOWN); + pinMode(SENSOR_CAPTURE_A, INPUT_PULLDOWN); + pinMode(SENSOR_CAPTURE, INPUT_PULLDOWN); + + pinMode(PULSE_DIRECTION, INPUT_PULLDOWN); + pinMode(PULSE_STROBE, INPUT_PULLDOWN); + + pinMode(SD_CS, INPUT_PULLDOWN); + + pinMode(QSPIDCS, INPUT_PULLDOWN); + pinMode(GPIOCLK, INPUT_PULLDOWN); + pinMode(QSPID0, INPUT_PULLDOWN); + pinMode(QSPID1, INPUT_PULLDOWN); + pinMode(QSPID2, INPUT_PULLDOWN); + pinMode(QSPID3, INPUT_PULLDOWN); + + pinMode(IRQ_CH1, INPUT); + pinMode(IRQ_CH2, INPUT); + pinMode(IRQ_CH3, INPUT); + pinMode(IRQ_CH4, INPUT); + pinMode(IRQ_CH5, INPUT); + pinMode(IRQ_CH6, INPUT); +} diff --git a/examples/Basic/PowerOnButton/PowerOnButton.ino b/examples/Basic/PowerOnButton/PowerOnButton.ino new file mode 100644 index 0000000..3576a2d --- /dev/null +++ b/examples/Basic/PowerOnButton/PowerOnButton.ino @@ -0,0 +1,58 @@ +/* + Test Power On button on LCD breakout board + + Circuit: + * Arduino Edge Control + * Arduino Edge Control LCD brekout board +*/ + +#include + +// Keep track of toggle-style press with an ISR +volatile bool buttonPressed { false }; +bool ledStatus { false }; + +void setup() +{ + Serial.begin(9600); + + for (auto timeout = millis() + 2500l; !Serial && millis() < timeout; delay(250)) + ; + + Serial.println("Hello, Arduino Edge Control!"); + + Power.on(PWR_3V3); + Power.on(PWR_VBAT); + + Wire.begin(); + + delay(500); + + Serial.print("IO Expander initializazion "); + if (!Expander.begin()) { + Serial.println("failed."); + Serial.println("Please, be sure to enable gated 3V3 and 5V power rails"); + Serial.println("via Power.on(PWR_3V3) and Power.on(PWR_VBAT)."); + } + Serial.println("succeeded."); + + Expander.pinMode(EXP_LED1, OUTPUT); + + pinMode(POWER_ON, INPUT); + // ISR for button press detection + attachInterrupt( + digitalPinToInterrupt(POWER_ON), [] { buttonPressed = true; }, FALLING); + +} + +void loop() +{ + if (buttonPressed == true) { + buttonPressed = false; + ledStatus = !ledStatus; + Serial.print(millis()); + Serial.println(" Pressed"); + } + + Expander.digitalWrite(EXP_LED1, ledStatus == true ? LOW : HIGH); +} diff --git a/examples/Basic/RealTimeClock/Helpers.h b/examples/Basic/RealTimeClock/Helpers.h new file mode 100644 index 0000000..ff26c31 --- /dev/null +++ b/examples/Basic/RealTimeClock/Helpers.h @@ -0,0 +1,132 @@ +#pragma once + +#include +#include +#include + +// Convert build time to UNIX time +time_t getBuildDateTime(bool local_time = true, int tz = 0) +{ + char s_month[5]; + int year; + + tm t; + time_t seconds; + + static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + + sscanf(__DATE__, "%s %d %d", s_month, &t.tm_mday, &year); + sscanf(__TIME__, "%2d %*c %2d %*c %2d", &t.tm_hour, &t.tm_min, &t.tm_sec); + + // Find where is s_month in month_names. Deduce month value. + t.tm_mon = (strstr(month_names, s_month) - month_names) / 3 + 1; + t.tm_year = year - 1900; + _rtc_maketime(&t, &seconds, RTC_FULL_LEAP_YEAR_SUPPORT); + + if (!local_time) { + if (tz > 200) { + tz = 0x100 - tz; // Handle negative values + seconds += (3600UL) * tz; + } else { + seconds -= (3600UL) * tz; + } + } + + return seconds; +} + +String getRTCDate() +{ + // APIs to get date fields. + auto years = RealTimeClock.getYears(); + auto months = RealTimeClock.getMonths(); + auto days = RealTimeClock.getDays(); + + char buf[12] {}; + + snprintf(buf, 11, "20%02d-%02d-%02d", years, months, days); + + return String(buf); +} + +String getRTCTime() +{ + // APIs to get time fields. + auto hours = RealTimeClock.getHours(); + auto minutes = RealTimeClock.getMinutes(); + auto seconds = RealTimeClock.getSeconds(); + + char buf[11] {}; + + snprintf(buf, 10, "%02d:%02d:%02d", hours, minutes, seconds); + + return String(buf); +} + +String getRTCDateTime() +{ + auto date = getRTCDate(); + auto time = getRTCTime(); + + auto dateTime = date + ' ' + time; + + return dateTime; +} + +String getLocaltime() +{ + char buffer[32]; + tm t; + _rtc_localtime(time(NULL), &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 32, "%Y-%m-%d %k:%M:%S", &t); + return String(buffer); +} + +String getLocaltime(const time_t& build_time) +{ + char buffer[32]; + tm t; + _rtc_localtime(build_time, &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 32, "%Y-%m-%d %k:%M:%S", &t); + return String(buffer); +} + +String getLocaltime(const char* fmt, bool local_time = true, int tz = 0) +{ + char buffer[64]; + time_t tmp_time = time(NULL); + tm t; + + if (!local_time) { + if (tz > 200) { + tz = 0x100 - tz; // Handle negative values + tmp_time -= (3600UL) * tz; + } else { + tmp_time += (3600UL) * tz; + } + } + + _rtc_localtime(tmp_time, &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 64, fmt, &t); + return String(buffer); +} + +String getLocaltime(const time_t build_time, const char* fmt, bool local_time = true, int tz = 0) +{ + char buffer[64]; + time_t tmp_time = build_time; + tm t; + + if (!local_time) { + if (tz > 200) { + tz = 0x100 - tz; // Handle negative values + tmp_time -= (3600UL) * tz; + } else { + tmp_time += (3600UL) * tz; + } + } + + _rtc_localtime(tmp_time, &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 64, fmt, &t); + return String(buffer); +} diff --git a/examples/Basic/RealTimeClock/RealTimeClock.ino b/examples/Basic/RealTimeClock/RealTimeClock.ino new file mode 100644 index 0000000..c224e91 --- /dev/null +++ b/examples/Basic/RealTimeClock/RealTimeClock.ino @@ -0,0 +1,67 @@ +/* + Arduino Edge Control - RTC Example + + This sketch shows how to use the RTC (PCF8563T) on the Arduino + Edge Control and how to configure the RTC's time registers. + + Circuit: + - Arduino Edge Control + - CR2032 Battery + - Optional: Arduino Edge Control LCD + Button brekout + +*/ + +#include "Helpers.h" +#include + +void setup() +{ + pinMode(POWER_ON, INPUT); + + Serial.begin(9600); + + for (auto timeout = millis() + 2500l; !Serial && millis() < timeout; delay(250)) + ; + + Serial.println("Hello, Arduino Edge Control!"); + + EdgeControl.begin(); + + Power.on(PWR_3V3); + Power.on(PWR_VBAT); + + Wire.begin(); + delay(500); + + Serial.print("Initializing the Real Time Clock..."); + while (!RealTimeClock.begin()) { + Serial.println(" failed! Retrying..."); + delay(250); + } + Serial.println(" done!"); + + // APIs to set date's fields: years, months, days, hours, minutes and seconds + // The RTC time can be set as epoch, using one of the following two options: + // - Calendar time: RealTimeClock.setEpoch(years, months, days, hours, minutes, seconds); + // - UTC time: RealTimeClock.setEpoch(date_in_seconds); + + // Set the RTC only when LCD's PowerOn button is pressed. + // YMMV. + if (digitalRead(POWER_ON) == LOW) { + Serial.println("Resetting the RTC to Sketch Build Datetime!"); + auto buildDateTime = getBuildDateTime(); + RealTimeClock.setEpoch(buildDateTime); + Serial.print("Build "); + } +} + +void loop() +{ + Serial.print("Date: "); + Serial.println(getRTCDateTime()); + + Serial.print("Unix time: "); + Serial.println(time(NULL)); + + delay(1000); +} diff --git a/examples/Basic/RealTimeClock_Alarm/Helpers.h b/examples/Basic/RealTimeClock_Alarm/Helpers.h new file mode 100644 index 0000000..5ad9f7a --- /dev/null +++ b/examples/Basic/RealTimeClock_Alarm/Helpers.h @@ -0,0 +1,93 @@ +#pragma once + +#include +#include + +// Convert build time to UNIX time +time_t getBuildDateTime(bool local_time = true, int tz = 0) +{ + char s_month[5]; + int year; + + tm t; + time_t seconds; + + static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + + sscanf(__DATE__, "%s %d %d", s_month, &t.tm_mday, &year); + sscanf(__TIME__, "%2d %*c %2d %*c %2d", &t.tm_hour, &t.tm_min, &t.tm_sec); + + // Find where is s_month in month_names. Deduce month value. + t.tm_mon = (strstr(month_names, s_month) - month_names) / 3 + 1; + t.tm_year = year - 1900; + _rtc_maketime(&t, &seconds, RTC_FULL_LEAP_YEAR_SUPPORT); + + if (!local_time) { + if (tz > 200) { + tz = 0x100 - tz; // Handle negative values + seconds += (3600UL) * tz; + } else { + seconds -= (3600UL) * tz; + } + } + + return seconds; +} + +String getLocaltime() +{ + char buffer[32]; + tm t; + _rtc_localtime(time(NULL), &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 32, "%Y-%m-%d %k:%M:%S", &t); + return String(buffer); +} + +String getLocaltime(const time_t& build_time) +{ + char buffer[32]; + tm t; + _rtc_localtime(build_time, &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 32, "%Y-%m-%d %k:%M:%S", &t); + return String(buffer); +} + +String getLocaltime(const char* fmt, bool local_time = true, int tz = 0) +{ + char buffer[64]; + time_t tmp_time = time(NULL); + tm t; + + if (!local_time) { + if (tz > 200) { + tz = 0x100 - tz; // Handle negative values + tmp_time -= (3600UL) * tz; + } else { + tmp_time += (3600UL) * tz; + } + } + + _rtc_localtime(tmp_time, &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 64, fmt, &t); + return String(buffer); +} + +String getLocaltime(const time_t build_time, const char* fmt, bool local_time = true, int tz = 0) +{ + char buffer[64]; + time_t tmp_time = build_time; + tm t; + + if (!local_time) { + if (tz > 200) { + tz = 0x100 - tz; // Handle negative values + tmp_time -= (3600UL) * tz; + } else { + tmp_time += (3600UL) * tz; + } + } + + _rtc_localtime(tmp_time, &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 64, fmt, &t); + return String(buffer); +} diff --git a/examples/Basic/RealTimeClock_Alarm/RealTimeClock_Alarm.ino b/examples/Basic/RealTimeClock_Alarm/RealTimeClock_Alarm.ino new file mode 100644 index 0000000..cb3a7c5 --- /dev/null +++ b/examples/Basic/RealTimeClock_Alarm/RealTimeClock_Alarm.ino @@ -0,0 +1,133 @@ +/* + Arduino Edge Control - RTC Alarm Example + + This sketch shows how to use the RTC (PCF8563T) on the Arduino + Edge Control and how to configure and use the RTC's alarm. + + Circuit: + - Arduino Edge Control + - CR2032 Battery + - Optional: Arduino Edge Control LCD + Button brekout + +*/ + +#include "Helpers.h" +#include + +volatile bool alarmFlag { false }; +byte alarmInterval { 1 }; + +void setup() +{ + Serial.begin(9600); + + for (auto timeout = millis() + 2500l; !Serial && millis() < timeout; delay(250)) + ; + + Serial.println("Hello, Arduino Edge Control!"); + + EdgeControl.begin(); + + Power.on(PWR_3V3); + Power.on(PWR_VBAT); + + Wire.begin(); + delay(500); + + Serial.print("Initializing the Real Time Clock..."); + while (!RealTimeClock.begin()) { + Serial.println(" failed! Retrying..."); + delay(250); + } + Serial.println(" done!"); + + // Set the RTC only when LCD's PowerOn button is pressed. + // YMMV. + if (digitalRead(POWER_ON) == LOW) { + auto buildDateTime = getBuildDateTime(); + RealTimeClock.setEpoch(buildDateTime); + Serial.print("Build "); + } + + Serial.print("Date: "); + Serial.println(getRTCDateTime()); + + // Enables Alarm on the RTC + RealTimeClock.enableAlarm(); + + // Set the minutes at which the alarm should rise + // Trigger in a minute + auto minutes = RealTimeClock.getMinutes(); + RealTimeClock.setMinuteAlarm(minutes + alarmInterval); + + // Attach an interrupt to the RTC interrupt pin + attachInterrupt( + digitalPinToInterrupt(IRQ_RTC), [] { alarmFlag = true; }, FALLING); + + Serial.println(); +} + +void loop() +{ + if (alarmFlag) { + Serial.println("Alarm!"); + + auto totalMinutes = RealTimeClock.getMinutes() + alarmInterval; + + // Take care of the 60-minute wrapping and... + auto minutesAlarm = totalMinutes % 60; + RealTimeClock.setMinuteAlarm(minutesAlarm); + + // don't forget to manage the hour increment. + if (totalMinutes >= 60) + RealTimeClock.setHourAlarm(RealTimeClock.getHours() + 1); + + RealTimeClock.clearAlarm(); + + // To disable the alarm uncomment the following line: + // RealTimeClock.disableAlarm(); + + alarmFlag = false; + } + + Serial.println(getRTCTime()); + delay(10000); +} + +String getRTCDate() +{ + // APIs to get date fields. + auto years = RealTimeClock.getYears(); + auto months = RealTimeClock.getMonths(); + auto days = RealTimeClock.getDays(); + + char buf[12] {}; + + snprintf(buf, 11, "20%02d-%02d-%02d", years, months, days); + + return String(buf); +} + +String getRTCTime() +{ + // APIs to get time fields. + auto hours = RealTimeClock.getHours(); + auto minutes = RealTimeClock.getMinutes(); + auto seconds = RealTimeClock.getSeconds(); + + char buf[11] {}; + + snprintf(buf, 10, "%02d:%02d:%02d", hours, minutes, seconds); + + return String(buf); +} + +String getRTCDateTime() +{ + auto date = getRTCDate(); + auto time = getRTCTime(); + + auto dateTime = date + ' ' + time; + + return dateTime; +} diff --git a/examples/Basic/RealTimeClock_LowPower/Helpers.h b/examples/Basic/RealTimeClock_LowPower/Helpers.h new file mode 100644 index 0000000..ff26c31 --- /dev/null +++ b/examples/Basic/RealTimeClock_LowPower/Helpers.h @@ -0,0 +1,132 @@ +#pragma once + +#include +#include +#include + +// Convert build time to UNIX time +time_t getBuildDateTime(bool local_time = true, int tz = 0) +{ + char s_month[5]; + int year; + + tm t; + time_t seconds; + + static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + + sscanf(__DATE__, "%s %d %d", s_month, &t.tm_mday, &year); + sscanf(__TIME__, "%2d %*c %2d %*c %2d", &t.tm_hour, &t.tm_min, &t.tm_sec); + + // Find where is s_month in month_names. Deduce month value. + t.tm_mon = (strstr(month_names, s_month) - month_names) / 3 + 1; + t.tm_year = year - 1900; + _rtc_maketime(&t, &seconds, RTC_FULL_LEAP_YEAR_SUPPORT); + + if (!local_time) { + if (tz > 200) { + tz = 0x100 - tz; // Handle negative values + seconds += (3600UL) * tz; + } else { + seconds -= (3600UL) * tz; + } + } + + return seconds; +} + +String getRTCDate() +{ + // APIs to get date fields. + auto years = RealTimeClock.getYears(); + auto months = RealTimeClock.getMonths(); + auto days = RealTimeClock.getDays(); + + char buf[12] {}; + + snprintf(buf, 11, "20%02d-%02d-%02d", years, months, days); + + return String(buf); +} + +String getRTCTime() +{ + // APIs to get time fields. + auto hours = RealTimeClock.getHours(); + auto minutes = RealTimeClock.getMinutes(); + auto seconds = RealTimeClock.getSeconds(); + + char buf[11] {}; + + snprintf(buf, 10, "%02d:%02d:%02d", hours, minutes, seconds); + + return String(buf); +} + +String getRTCDateTime() +{ + auto date = getRTCDate(); + auto time = getRTCTime(); + + auto dateTime = date + ' ' + time; + + return dateTime; +} + +String getLocaltime() +{ + char buffer[32]; + tm t; + _rtc_localtime(time(NULL), &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 32, "%Y-%m-%d %k:%M:%S", &t); + return String(buffer); +} + +String getLocaltime(const time_t& build_time) +{ + char buffer[32]; + tm t; + _rtc_localtime(build_time, &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 32, "%Y-%m-%d %k:%M:%S", &t); + return String(buffer); +} + +String getLocaltime(const char* fmt, bool local_time = true, int tz = 0) +{ + char buffer[64]; + time_t tmp_time = time(NULL); + tm t; + + if (!local_time) { + if (tz > 200) { + tz = 0x100 - tz; // Handle negative values + tmp_time -= (3600UL) * tz; + } else { + tmp_time += (3600UL) * tz; + } + } + + _rtc_localtime(tmp_time, &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 64, fmt, &t); + return String(buffer); +} + +String getLocaltime(const time_t build_time, const char* fmt, bool local_time = true, int tz = 0) +{ + char buffer[64]; + time_t tmp_time = build_time; + tm t; + + if (!local_time) { + if (tz > 200) { + tz = 0x100 - tz; // Handle negative values + tmp_time -= (3600UL) * tz; + } else { + tmp_time += (3600UL) * tz; + } + } + + _rtc_localtime(tmp_time, &t, RTC_FULL_LEAP_YEAR_SUPPORT); + strftime(buffer, 64, fmt, &t); + return String(buffer); +} diff --git a/examples/Basic/RealTimeClock_LowPower/RealTimeClock_LowPower.ino b/examples/Basic/RealTimeClock_LowPower/RealTimeClock_LowPower.ino new file mode 100644 index 0000000..41815b2 --- /dev/null +++ b/examples/Basic/RealTimeClock_LowPower/RealTimeClock_LowPower.ino @@ -0,0 +1,109 @@ +/* + Arduino Edge Control - RTC Low Power Example + + This sketch shows how to use the RTC (PCF8563T) on the Arduino + Edge Control and how to configure and use the RTC on Low Power mode. + + Circuit: + - Arduino Edge Control + - CR2032 Battery + - Optional: Arduino Edge Control LCD + Button brekout + +*/ + +#include "Helpers.h" +#include +#include + +void setup() +{ + Serial.begin(9600); + + for (auto timeout = millis() + 2500l; !Serial && millis() < timeout; delay(250)) + ; + + Serial.println("Hello, Arduino Edge Control!"); + + EdgeControl.begin(); + + Power.on(PWR_3V3); + Power.on(PWR_VBAT); + + Wire.begin(); + delay(500); + + Serial.print("Initializing the Real Time Clock..."); + while (!RealTimeClock.begin()) { + Serial.println(" failed! Retrying..."); + delay(250); + } + Serial.println(" done!"); + + // Set the RTC only when LCD's PowerOn button is pressed. + // YMMV. + if (digitalRead(POWER_ON) == LOW) { + auto buildDateTime = getBuildDateTime(); + RealTimeClock.setEpoch(buildDateTime); + Serial.print("Build "); + } + + Serial.print("Date: "); + Serial.println(getRTCDateTime()); + + delay(5000); + + Wire.end(); + Serial.end(); + Serial1.end(); + + Power.off(PWR_3V3); + Power.off(PWR_VBAT); + + mbed::mbed_file_handle(STDIN_FILENO)->enable_input(false); + PluggableUSBD().deinit(); +} + +void loop() +{ + delay(10000); +} + +void powerDown() +{ + pinMode(I2C_SDA, INPUT_PULLDOWN); + pinMode(I2C_SCL, INPUT_PULLDOWN); + pinMode(I2C_SDA1, INPUT_PULLDOWN); + pinMode(I2C_SCL1, INPUT_PULLDOWN); + + pinMode(VBAT_PROBE, INPUT_PULLDOWN); + + pinMode(CMD_TRIAC_1, INPUT_PULLDOWN); + pinMode(CMD_TRIAC_2, INPUT_PULLDOWN); + pinMode(CMD_TRIAC_3, INPUT_PULLDOWN); + pinMode(CMD_TRIAC_4, INPUT_PULLDOWN); + + pinMode(SENSOR_COMMON, INPUT_PULLDOWN); + pinMode(SENSOR_CALIB, INPUT_PULLDOWN); + pinMode(SENSOR_INPUT_ADC, INPUT_PULLDOWN); + pinMode(SENSOR_CAPTURE_A, INPUT_PULLDOWN); + pinMode(SENSOR_CAPTURE, INPUT_PULLDOWN); + + pinMode(PULSE_DIRECTION, INPUT_PULLDOWN); + pinMode(PULSE_STROBE, INPUT_PULLDOWN); + + pinMode(SD_CS, INPUT_PULLDOWN); + + pinMode(QSPIDCS, INPUT_PULLDOWN); + pinMode(GPIOCLK, INPUT_PULLDOWN); + pinMode(QSPID0, INPUT_PULLDOWN); + pinMode(QSPID1, INPUT_PULLDOWN); + pinMode(QSPID2, INPUT_PULLDOWN); + pinMode(QSPID3, INPUT_PULLDOWN); + + pinMode(IRQ_CH1, INPUT_PULLDOWN); + pinMode(IRQ_CH2, INPUT_PULLDOWN); + pinMode(IRQ_CH3, INPUT_PULLDOWN); + pinMode(IRQ_CH4, INPUT_PULLDOWN); + pinMode(IRQ_CH5, INPUT_PULLDOWN); + pinMode(IRQ_CH6, INPUT_PULLDOWN); +} diff --git a/examples/Basic/Watermark10k/Watermark10k.ino b/examples/Basic/Watermark10k/Watermark10k.ino index 4f0c11c..86d7ddb 100644 --- a/examples/Basic/Watermark10k/Watermark10k.ino +++ b/examples/Basic/Watermark10k/Watermark10k.ino @@ -10,6 +10,7 @@ void setup() while (!Serial && millis() < startNow) ; + EdgeControl.begin(); delay(2000); Serial.println("Hello, 10k"); @@ -18,12 +19,12 @@ void setup() Power.on(PWR_VBAT); Wire.begin(); - Expander.begin(); + delay(500); Serial.print("Waiting for IO Expander Initialization..."); - while (!Expander) { + while (!Expander.begin()) { Serial.print("."); - delay(100); + delay(250); } Serial.println(" done."); @@ -36,7 +37,6 @@ void setup() Watermark.commonMode(OUTPUT); Watermark.commonWrite(HIGH); - Watermark.enable(); } void loop() @@ -56,8 +56,10 @@ int wmkAvgAnalogRead(pin_size_t pin) constexpr size_t count { 10 }; unsigned int sum { 0 }; + Watermark.enable(); for (auto i = 0u; i < count; i ++) sum += Watermark.analogRead(pin); + Watermark.disable(); return sum / count; } diff --git a/examples/Basic/WatermarkMega/WatermarkMega.ino b/examples/Basic/WatermarkMega/WatermarkMega.ino new file mode 100644 index 0000000..ff25947 --- /dev/null +++ b/examples/Basic/WatermarkMega/WatermarkMega.ino @@ -0,0 +1,139 @@ +/* + This sketch is the implementation of the classic Watermark example + for Arduino Mega ported to the Arduino Edge Control. + + Please, refer to https://www.irrometer.com/200ss.html for further info. + + Another algorithm that can be implemented using the Watermark circuits + on the Edge Control is the one described at + https://medium.com/fasal-engineering/a-low-cost-circuit-to-read-from-multiple-watermark-irrometer-200ss-sensors-a4c838da233a + + Requirements: + - Arduino Edge Control + - Watermark Sensor + - External 12V power supply + + Circuit: + - Connect PS 12V and GND to BATT+ and GND pins + - Connect the two sensor's cables to WATERMARK COMM and INPUT 1 pins + +*/ + +#include + +constexpr auto adcResolution { 12 }; + +// You will need a proper temperature value to get correct results +auto refTemperature { 24.5f }; + +void setup() +{ + Serial.begin(115200); + + // Wait for Serial or start after 2.5s + for (const auto startNow = millis() + 2500; !Serial && millis() < startNow; delay(250)); + + EdgeControl.begin(); + delay(2000); + + Serial.println("Hello, Watermark Mega"); + + Power.on(PWR_3V3); + Power.on(PWR_VBAT); + + Wire.begin(); + delay(500); + + Serial.print("Waiting for IO Expander Initialization..."); + while (!Expander.begin()) { + Serial.print("."); + delay(250); + } + Serial.println(" done."); + + Watermark.begin(); + Serial.println("Watermark OK"); +} + +void loop() +{ + auto wm = getWatermark(WATERMARK_CH01); + Serial.print("Watermark = "); + Serial.print(wm); + Serial.println("kPa"); + + delay(1000); +} + + +int getAverageWatermarkRead(pin_size_t pin) +{ + constexpr size_t count { 20 }; + int sum { 0 }; + + Watermark.calibrationMode(OUTPUT); + Watermark.calibrationWrite(LOW); + + Watermark.commonMode(OUTPUT); + + Watermark.enable(); + + for (auto i = 0u; i < count; i++) { + Watermark.commonWrite(HIGH); + delay(2); + sum += Watermark.analogRead(pin); + Watermark.commonWrite(LOW); + } + + Watermark.disable(); + + return sum / count; +} + +float getWatermark(pin_size_t pin) +{ + constexpr unsigned int calibResistor { 7870 }; + constexpr long openResistance { 35000 }; + constexpr long shortResistance { 200 }; + constexpr long shortkPa { 240 }; + constexpr long openkPa { 255 }; + + constexpr auto maxValue { 1 << adcResolution }; + constexpr float toV { 3.3f / float { maxValue } }; + + float kPa; + + auto val = getAverageWatermarkRead(pin); + + if (val == 0) + return openkPa; + + auto resistor = calibResistor * float { maxValue - val } / float { val }; + + if (resistor > 550.f) { + if (resistor > 8000.f) { + kPa = -2.246f - 5.239f * (resistor / 1500.f) * (1.f + .018f * (refTemperature - 24.f)) - .06756f * (resistor / 1500.f) * (resistor / 1500.f) * ((1.f + 0.018f * (refTemperature - 24.f)) * (1.f + 0.018f * (refTemperature - 24.f))); + } else if (resistor > 1500.f) { + kPa = (-3.213f * (resistor / 1500.f) - 4.093f) / (1.f - 0.009733f * (resistor / 1500.f) - 0.01205f * (refTemperature)); + } else { + kPa = ((resistor / 1500.f) * 23.156f - 12.736f) * (1.f + 0.018f * (refTemperature - 24.f)); + } + } else { + if (resistor > 300.f) + kPa = 0.f; + if (resistor < 300.f && resistor >= shortResistance) + kPa = shortkPa; // 240 is a fault code for sensor terminal short + } + + if (resistor >= openResistance) { + kPa = openkPa; // 255 is a fault code for open circuit or sensor not present + } + + Serial.print("Watermark average analogRead value: "); + Serial.print(val); + Serial.print(" - Calculated Resistor: "); + Serial.print(resistor); + Serial.println(); + + return abs(kPa); +} diff --git a/examples/RPC/BlinkOverSerial/BlinkOverSerial.ino b/examples/RPC/BlinkOverSerial/BlinkOverSerial.ino index e13f61c..1c6defe 100644 --- a/examples/RPC/BlinkOverSerial/BlinkOverSerial.ino +++ b/examples/RPC/BlinkOverSerial/BlinkOverSerial.ino @@ -1,23 +1,17 @@ -/* Sketch to load on the MKR - * - * - * - void setup() { - Serial1.begin(9600); - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); - - delay(1000); - } +/* + This sketch shows how to use an MKR board connected to one of the + two available slots. The Edge Control and the MKR board will communicate + over UART connection. + + Circuit: + - Arduino Edge Control + - Any Arduino MKR Board connected to MKR Slot 2 + - External 12V Power Supply + + To get the example working, please, load the extras/BlinkFromSerial + sketch on the MKR board. + - void loop() { - if (Serial1.available()) { - auto c = Serial1.read(); - digitalWrite(LED_BUILTIN, c); - } - } -* -* */ #include @@ -29,12 +23,17 @@ void setup() EdgeControl.begin(); Power.on(PWR_3V3); Power.on(PWR_VBAT); + + // Power on the MKR on slot 2 Power.on(PWR_MKR2); // Wait for MKR to power on delay(5000); + // Open the serial communication with the MKR board on slot 2... SerialMKR2.begin(115200); + + // ... and ait for the serial communication from the MKR board while (!SerialMKR2) { delay(500); } @@ -45,4 +44,4 @@ void loop() SerialMKR2.write(led); led = !led; delay(1000); -} \ No newline at end of file +} diff --git a/extras/RPC/BlinkFromSerial/BlinkFromSerial.ino b/extras/RPC/BlinkFromSerial/BlinkFromSerial.ino new file mode 100644 index 0000000..7a687bb --- /dev/null +++ b/extras/RPC/BlinkFromSerial/BlinkFromSerial.ino @@ -0,0 +1,23 @@ +#include + +void setup() +{ + // Optionally disable the LiPo charger + PMIC.begin(); + PMIC.disableCharge(); + + // Open the communication to the Edge Control + Serial1.begin(115200); + + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, LOW); +} + +void loop() +{ + // Wait for data + if (Serial1.available()) { + auto c = Serial1.read(); + digitalWrite(LED_BUILTIN, c); + } +} diff --git a/library.properties b/library.properties index 244a910..91d8fad 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Arduino_EdgeControl -version=0.1.0 +version=0.2.0 author=Arduino maintainer=Arduino sentence=Arduino Library for Arduino Edge Control diff --git a/src/Arduino_EdgeControl.h b/src/Arduino_EdgeControl.h index 6366502..21bf14e 100644 --- a/src/Arduino_EdgeControl.h +++ b/src/Arduino_EdgeControl.h @@ -17,4 +17,5 @@ #include "EdgeControl_Input.h" #include "EdgeControl_Watermark.h" #include "EdgeControl_Latching.h" -#include "EdgeControl_SolidStateRelay.h" \ No newline at end of file +#include "EdgeControl_SolidStateRelay.h" +#include "EdgeControl_RealTimeClock.h" diff --git a/src/EdgeControl_RealTimeClock.cpp b/src/EdgeControl_RealTimeClock.cpp new file mode 100644 index 0000000..ee76d4d --- /dev/null +++ b/src/EdgeControl_RealTimeClock.cpp @@ -0,0 +1,413 @@ +/* + This file is part of the Arduino Edge Control library. + Copyright (C) 2022 Arduino AG (http://www.arduino.cc/) + SPDX-License-Identifier: MPL-2.0 + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. +*/ + +#include "EdgeControl_RealTimeClock.h" + +#define PCF8563T_ADDRESS 0x51 +#define PCF8563T_STATUS_2_REG 0X01 +#define PCF8563T_VL_SECONDS_REG 0X02 +#define PCF8563T_MINUTES_REG 0x03 +#define PCF8563T_HOURS_REG 0X04 +#define PCF8563T_DAYS_REG 0x05 +#define PCF8563T_MONTHS_REG 0x07 +#define PCF8563T_YEARS_REG 0x08 + +// alarm management +#define PCF8563T_MINUTE_ALARM_REG 0x09 +#define PCF8563T_MINUTE_ALARM_AE_M_MASK 0x80 +#define PCF8563T_MINUTE_ALARM_ON 0x7F + +#define PCF8563T_HOUR_ALARM_REG 0x0A +#define PCF8563T_HOUR_ALARM_AE_H_MASK 0x80 +#define PCF8563T_HOUR_ALARM_ON 0x7F + +#define PCF8563T_DAY_ALARM_REG 0x0B +#define PCF8563T_DAY_ALARM_AE_D_MASK 0x80 +#define PCF8563T_DAY_ALARM_ON 0x7F + +#define PCF8563T_TIMER_CONTROL_REG 0X0E +#define PCF8563T_TIMER_CONTROL_ON 0x80 +#define PCF8563T_TIMER_CONTROL_OFF 0x7F + +#define PCF8563T_STATUS_2_AIE_MASK 0x02 +#define PCF8563T_STATUS_2_CLEAR_INT 0xF7 +#define PCF8563T_STATUS_2_INT_OFF 0x7d + +/** + * Object constructor + * + */ +EdgeControl_RealTimeClockClass::EdgeControl_RealTimeClockClass() +{ +} + +/** + * Start the communication with the RTC + * Initialize I2C (Wire) bus and check if the chip is connected by sending an ACK on the I2C bus. + * @return true if the RTC Controller is on the I2C bus, false if it is not. + * + */ +bool EdgeControl_RealTimeClockClass::begin() +{ + Wire.beginTransmission(PCF8563T_ADDRESS); + if (!Wire.endTransmission()) { + return true; + } + return false; +} + +/** + * Set Year number's value + * Save an unsigned byte with the Year's value + * @param years Year's unsigned byte + */ +void EdgeControl_RealTimeClockClass::setYears(uint8_t years) +{ + uint8_t dec = years / 10; + uint8_t unit = years - (dec * 10); + writeByte(PCF8563T_YEARS_REG, ((dec << 4) + unit)); +} + +/** + * Set Month number's value + * Save an unsigned byte with the Month's value + * @param months Month's unsigned byte (0 to 12) + */ +void EdgeControl_RealTimeClockClass::setMonths(uint8_t months) +{ + uint8_t offset = 0; + if (months > 9) { + offset = 6; + } + writeByte(PCF8563T_MONTHS_REG, months + offset); +} + +/** + * Set Day number's value + * Save an unsigned byte with the Day's value + * @param days day's unsigned byte + */ +void EdgeControl_RealTimeClockClass::setDays(uint8_t days) +{ + uint8_t dec = days / 10; + uint8_t unit = days - (dec * 10); + writeByte(PCF8563T_DAYS_REG, ((dec << 4) + unit)); +} + +/** + * Set Hour(s) number's value + * Save an unsigned byte with the Hour(s) value + * @param hours hour unsigned byte (0 - 23) + */ +void EdgeControl_RealTimeClockClass::setHours(uint8_t hours) +{ + uint8_t dec = hours / 10; + uint8_t unit = hours - (dec * 10); + writeByte(PCF8563T_HOURS_REG, ((dec << 4) + unit)); // check formula on datasheet val + 6 * (val / 10) +} + +/** + * Set Minute(s) number's value + * Save an unsigned byte with the Minute(s) value + * @param minutes minute unsigned byte (0-60) + */ +void EdgeControl_RealTimeClockClass::setMinutes(uint8_t minutes) +{ + uint8_t dec = minutes / 10; + uint8_t unit = minutes - (dec * 10); + writeByte(PCF8563T_MINUTES_REG, ((dec << 4) + unit)); +} + +/** + * Set Second(s) number's value + * Save an unsigned byte with the Second(s) value + * @param seconds Second(s) unsigned byte (0-60) + */ +void EdgeControl_RealTimeClockClass::setSeconds(uint8_t seconds) +{ + uint8_t dec = seconds / 10; + uint8_t unit = seconds - (dec * 10); + writeByte(PCF8563T_VL_SECONDS_REG, ((dec << 4) + unit)); +} + +/** + * Get Year(s) number's value + * Get unsigned byte with the Year(s) value + * @return byte with Year(s) value + */ +uint8_t EdgeControl_RealTimeClockClass::getYears() +{ + uint8_t years = readByte(PCF8563T_YEARS_REG); + return (years & 0x0F) + ((years >> 4) * 10); +} + +/** + * Get Month(s) month's value + * Get unsigned byte with the month(s) value + * @return byte with Month(s) value + */ +uint8_t EdgeControl_RealTimeClockClass::getMonths() +{ + uint8_t months = readByte(PCF8563T_MONTHS_REG) & 0x1F; + if (months > 9) { + return months - 6; + } else { + return months; + } +} + +/** + * Get Day(s) number's value + * Get unsigned byte with the Day(s) value + * @return byte with Day(s) value + */ +uint8_t EdgeControl_RealTimeClockClass::getDays() +{ + uint8_t days = readByte(PCF8563T_DAYS_REG) & 0x3F; + return ((days & 0x0F) + (((days >> 4) & 0x03) * 10)); +} + +/** + * Get Hour(s) number's value + * Get unsigned byte with the Hour(s) value + * @return byte with Hour(s) value + */ +uint8_t EdgeControl_RealTimeClockClass::getHours() +{ + uint8_t hours = readByte(PCF8563T_HOURS_REG) & 0x3F; + return (hours & 0x0F) + ((hours >> 4) * 10); +} + +/** + * Get Minute(s) number's value + * Get unsigned byte with the Minute(s) value + * @return byte with Minute(s) value + */ +uint8_t EdgeControl_RealTimeClockClass::getMinutes() +{ + uint8_t minutes = (readByte(PCF8563T_MINUTES_REG)) & 0x7F; + return (minutes & 0x0F) + ((minutes >> 4) * 10); +} + +/** + * Get Second(s) number's value + * Get unsigned byte with the Second(s) value + * @return byte with Second(s) value + */ +uint8_t EdgeControl_RealTimeClockClass::getSeconds() +{ + uint8_t seconds = readByte(PCF8563T_VL_SECONDS_REG) & 0x7F; + return (seconds & 0x0F) + ((seconds >> 4) * 10); +} + +/** + * Set time Epoch format + * + */ +void EdgeControl_RealTimeClockClass::setEpoch() +{ + struct tm time; + time.tm_sec = getSeconds(); + time.tm_min = getMinutes(); + time.tm_hour = getHours(); + time.tm_mday = getDays(); + time.tm_mon = getMonths() - 1; + time.tm_year = getYears() + 100; + time_t seconds; + _rtc_maketime(&time, &seconds, RTC_FULL_LEAP_YEAR_SUPPORT); + set_time(seconds); +} + +/** + * Set time with Epoch format + * + * + * @param seconds number of seconds (time_t type) + */ +void EdgeControl_RealTimeClockClass::setEpoch(time_t seconds) +{ + struct tm time; + _rtc_localtime(seconds, &time, RTC_FULL_LEAP_YEAR_SUPPORT); + + setSeconds(time.tm_sec); + setMinutes(time.tm_min); + setHours(time.tm_hour); + setDays(time.tm_mday); + setMonths(time.tm_mon + 1); + setYears((time.tm_year - 100)); + set_time(seconds); +} + +/** + * Set time with Epoch format + * + * Convert the input values to Epoch format + * example: Tue, 06 Jul 2021 11:55:27 GMT -> 1625572527 + * + * @param years number of years + * @param mohths number of months + * @param days number of days + * @param hours number of hours + * @param minutes number of minutes + * @param seconds number of seconds + */ +void EdgeControl_RealTimeClockClass::setEpoch(uint8_t years, uint8_t months, uint8_t days, uint8_t hours, uint8_t minutes, uint8_t seconds) +{ + struct tm time; + time_t utcsec; + + time.tm_sec = seconds; + time.tm_min = minutes; + time.tm_hour = hours; + time.tm_mday = days; + time.tm_mon = months - 1; + time.tm_year = years + 100; // year since 1900 + + _rtc_maketime(&time, &utcsec, RTC_FULL_LEAP_YEAR_SUPPORT); + set_time(utcsec); +} + +/** + * Get epoch number + * Convert real time to difference between actual time and Epoch(Unix time) + * Saved into time_t type + * + * example: 1625572527 -> Tue, 06 Jul 2021 11:55:27 GMT + * + * @return number of seconds after Unix time (time_t type) + */ +time_t EdgeControl_RealTimeClockClass::getEpoch() +{ + struct tm time; + time_t seconds; + + time.tm_sec = getSeconds(); + time.tm_min = getMinutes(); + time.tm_hour = getHours(); + time.tm_mday = getDays(); + time.tm_mon = getMonths() - 1; + time.tm_year = getYears() + 100; // year since 1900 + + _rtc_maketime(&time, &seconds, RTC_FULL_LEAP_YEAR_SUPPORT); + return seconds; +} + +/** + * Enable alarm + * + */ +void EdgeControl_RealTimeClockClass::enableAlarm() +{ + writeByte(PCF8563T_STATUS_2_REG, (readByte(PCF8563T_STATUS_2_REG) & PCF8563T_STATUS_2_CLEAR_INT) | PCF8563T_STATUS_2_AIE_MASK); +} + +/** + * Disable alarm + * + */ +void EdgeControl_RealTimeClockClass::disableAlarm() +{ + writeByte(PCF8563T_STATUS_2_REG, (readByte(PCF8563T_STATUS_2_REG) & PCF8563T_STATUS_2_INT_OFF)); +} + +/** + * Clear alarm status + * + */ +void EdgeControl_RealTimeClockClass::clearAlarm() +{ + writeByte(PCF8563T_STATUS_2_REG, (readByte(PCF8563T_STATUS_2_REG) & PCF8563T_STATUS_2_CLEAR_INT) | PCF8563T_STATUS_2_AIE_MASK); +} + +/** + * Set alarm's minute + * + * @param minutes minute(s) value for the Alarm (byte type) + */ +void EdgeControl_RealTimeClockClass::setMinuteAlarm(uint8_t minutes) +{ + uint8_t dec = minutes / 10; + uint8_t unit = minutes - (dec * 10); + uint8_t min_alarm = PCF8563T_MINUTE_ALARM_ON & ((dec << 4) + unit); + writeByte(PCF8563T_MINUTE_ALARM_REG, min_alarm); +} + +/** + * Disable and clear the minute of the Alarm + * + */ +void EdgeControl_RealTimeClockClass::disableMinuteAlarm() +{ + writeByte(PCF8563T_MINUTE_ALARM_REG, readByte(PCF8563T_MINUTE_ALARM_REG) | PCF8563T_MINUTE_ALARM_AE_M_MASK); +} + +/** + * Set Alarm's hour + * + * @param hours hour(s) value for the Alarm (byte type) + */ +void EdgeControl_RealTimeClockClass::setHourAlarm(uint8_t hours) +{ + uint8_t dec = hours / 10; + uint8_t unit = hours - (dec * 10); + uint8_t hour_alarm = PCF8563T_HOUR_ALARM_ON & ((dec << 4) + unit); + writeByte(PCF8563T_HOUR_ALARM_REG, hour_alarm); // check formula on datasheet val + 6 * (val / 10) +} + +/** + * Disable and clear the hour of the Alarm + * + */ +void EdgeControl_RealTimeClockClass::disableHourAlarm() +{ + writeByte(PCF8563T_HOUR_ALARM_REG, readByte(PCF8563T_HOUR_ALARM_REG) | PCF8563T_HOUR_ALARM_AE_H_MASK); +} + +/** + * Set Alarm's day + * + * @param days day value for the Alarm (byte type) + */ +void EdgeControl_RealTimeClockClass::setDayAlarm(uint8_t days) +{ + uint8_t dec = days / 10; + uint8_t unit = days - (dec * 10); + uint8_t day_alarm = PCF8563T_DAY_ALARM_ON & ((dec << 4) + unit); + writeByte(PCF8563T_DAY_ALARM_REG, day_alarm); +} + +/** + * Disable and clear the day of the Alarm + * + */ +void EdgeControl_RealTimeClockClass::disableDayAlarm() +{ + writeByte(PCF8563T_DAY_ALARM_REG, readByte(PCF8563T_DAY_ALARM_REG) | PCF8563T_DAY_ALARM_AE_D_MASK); +} + +void EdgeControl_RealTimeClockClass::writeByte(uint8_t regAddres, uint8_t data) +{ + Wire.beginTransmission(PCF8563T_ADDRESS); + Wire.write(regAddres); + Wire.write(data); + Wire.endTransmission(); +} + +uint8_t EdgeControl_RealTimeClockClass::readByte(uint8_t regAddres) +{ + Wire.beginTransmission(PCF8563T_ADDRESS); + Wire.write(regAddres); // Day Register + Wire.endTransmission(); + Wire.requestFrom(PCF8563T_ADDRESS, 1); + + return Wire.read(); +} + +EdgeControl_RealTimeClockClass RealTimeClock {}; diff --git a/src/EdgeControl_RealTimeClock.h b/src/EdgeControl_RealTimeClock.h new file mode 100644 index 0000000..fcca651 --- /dev/null +++ b/src/EdgeControl_RealTimeClock.h @@ -0,0 +1,60 @@ +/* + This file is part of the Arduino Edge Control library. + Copyright (C) 2022 Arduino AG (http://www.arduino.cc/) + SPDX-License-Identifier: MPL-2.0 + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +#include +#include +#include +#include +#include + +#define IRQ_RTC IRQ_CH6 + +class EdgeControl_RealTimeClockClass { + +public: + EdgeControl_RealTimeClockClass(); + bool begin(); + void setYears(uint8_t years); + void setMonths(uint8_t months); + void setDays(uint8_t days); + void setHours(uint8_t hours); + void setMinutes(uint8_t minutes); + void setSeconds(uint8_t seconds); + + uint8_t getYears(); + uint8_t getMonths(); + uint8_t getDays(); + uint8_t getHours(); + uint8_t getMinutes(); + uint8_t getSeconds(); + + void setEpoch(); + void setEpoch(uint8_t years, uint8_t months, uint8_t days, uint8_t hours, uint8_t minutes, uint8_t seconds); + void setEpoch(time_t seconds); + time_t getEpoch(); + + void enableAlarm(); + void disableAlarm(); + void clearAlarm(); + void setMinuteAlarm(uint8_t minutes); + void disableMinuteAlarm(); + void setHourAlarm(uint8_t hours); + void disableHourAlarm(); + void setDayAlarm(uint8_t days); + void disableDayAlarm(); + +private: + void writeByte(uint8_t regAddres, uint8_t data); + uint8_t readByte(uint8_t regAddres); +}; + +extern EdgeControl_RealTimeClockClass RealTimeClock; diff --git a/src/lib/ioexpander/TCA6424A.cpp b/src/lib/ioexpander/TCA6424A.cpp index 851ee6b..3edc84a 100644 --- a/src/lib/ioexpander/TCA6424A.cpp +++ b/src/lib/ioexpander/TCA6424A.cpp @@ -87,7 +87,7 @@ uint8_t TCA6424A::readBank(uint8_t bank) { * @param banks Container for all bank's pin values (P00-P27) */ void TCA6424A::readAll(uint8_t *banks) { - I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0, 3, banks); + I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0 | TCA6424A_AUTO_INCREMENT, 3, banks); } /** Get all pin logic levels from all banks. * Reads into individual 1-byte containers. @@ -96,7 +96,7 @@ void TCA6424A::readAll(uint8_t *banks) { * @param bank2 Container for Bank 2's pin values (P20-P27) */ void TCA6424A::readAll(uint8_t *bank0, uint8_t *bank1, uint8_t *bank2) { - I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0, 3, buffer); + I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0 | TCA6424A_AUTO_INCREMENT, 3, buffer); *bank0 = buffer[0]; *bank1 = buffer[1]; *bank2 = buffer[2]; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy