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/AlarmTasks.cpp b/examples/Application/IrrigationSimple/AlarmTasks.cpp index c51427e..68a704d 100644 --- a/examples/Application/IrrigationSimple/AlarmTasks.cpp +++ b/examples/Application/IrrigationSimple/AlarmTasks.cpp @@ -48,7 +48,7 @@ AlarmTask parseAlarmTask(const String line) AlarmTask task; line.toCharArray(buf, len); - auto n = sscanf(buf, "%s %d %d %d %d %s", &method, &task.day, &task.hour, &task.min, &task.sec, cmd); + auto n = sscanf(buf, "%s %d %d %d %d %s", method, &task.day, &task.hour, &task.min, &task.sec, cmd); if (n != 6) return task; diff --git a/examples/Application/IrrigationSimple/Helpers.cpp b/examples/Application/IrrigationSimple/Helpers.cpp index e7facfc..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: "); @@ -67,30 +67,30 @@ float getAverage05VRead(int pin) analogReadResolution(ADC_RESOLUTION); Input.enable(); - for (auto i = 0; i < loops; i++) + for (auto i = 0u; i < loops; i++) tot += Input.analogRead(pin); Input.disable(); - const auto avg = float { tot } * toV / float { loops }; + const auto avg = static_cast(tot) * toV / static_cast(loops); return avg / rDiv; } -int getAverageInputRead(int pin, const size_t loops) +uint16_t getAverageInputRead(int pin, const size_t loops) { unsigned int tot { 0 }; analogReadResolution(ADC_RESOLUTION); Input.enable(); - for (auto i = 0; i < loops; i++) + for (auto i = 0u; i < loops; i++) tot += Input.analogRead(pin); Input.disable(); return tot / loops; } -int getMoisturePerc(int pin) +uint8_t getMoisturePerc(int pin) { // Keep track ok dry/wet values. YMMV. static long dryValue { 2160 }; @@ -106,5 +106,5 @@ int getMoisturePerc(int pin) auto perc = map(val, dryValue, wetValue, 0, 100); - return perc; + return static_cast(perc); } diff --git a/examples/Application/IrrigationSimple/Helpers.h b/examples/Application/IrrigationSimple/Helpers.h index 867ce14..dd3153e 100644 --- a/examples/Application/IrrigationSimple/Helpers.h +++ b/examples/Application/IrrigationSimple/Helpers.h @@ -11,10 +11,10 @@ void setSystemClock(String date = __DATE__, String time = __TIME__); void statusPrint(); -int getAverageInputRead(int pin, size_t loops = 20); +uint16_t getAverageInputRead(int pin, size_t loops = 20); float getAverage05VRead(int pin); -int getMoisturePerc(int pin); +uint8_t getMoisturePerc(int pin); extern std::list alarmTabIDs; extern std::list alarmSketchIDs; -extern std::list dataPoints; \ No newline at end of file +extern std::list dataPoints; 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/AlarmTasks.cpp b/examples/Application/IrrigationSimpleLCD/AlarmTasks.cpp index c51427e..68a704d 100644 --- a/examples/Application/IrrigationSimpleLCD/AlarmTasks.cpp +++ b/examples/Application/IrrigationSimpleLCD/AlarmTasks.cpp @@ -48,7 +48,7 @@ AlarmTask parseAlarmTask(const String line) AlarmTask task; line.toCharArray(buf, len); - auto n = sscanf(buf, "%s %d %d %d %d %s", &method, &task.day, &task.hour, &task.min, &task.sec, cmd); + auto n = sscanf(buf, "%s %d %d %d %d %s", method, &task.day, &task.hour, &task.min, &task.sec, cmd); if (n != 6) return task; diff --git a/examples/Application/IrrigationSimpleLCD/Helpers.cpp b/examples/Application/IrrigationSimpleLCD/Helpers.cpp index b850d6c..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: "); @@ -110,30 +110,30 @@ float getAverage05VRead(int pin) analogReadResolution(ADC_RESOLUTION); Input.enable(); - for (auto i = 0; i < loops; i++) + for (auto i = 0u; i < loops; i++) tot += Input.analogRead(pin); Input.disable(); - const auto avg = float { tot } * toV / float { loops }; + const auto avg = static_cast(tot) * toV / static_cast(loops); return avg / rDiv; } -int getAverageInputRead(int pin, const size_t loops) +uint16_t getAverageInputRead(int pin, const size_t loops) { unsigned int tot { 0 }; analogReadResolution(ADC_RESOLUTION); Input.enable(); - for (auto i = 0; i < loops; i++) + for (auto i = 0u; i < loops; i++) tot += Input.analogRead(pin); Input.disable(); return tot / loops; } -int getMoisturePerc(int pin) +uint8_t getMoisturePerc(int pin) { // Keep track ok dry/wet values. YMMV. static long dryValue { 2160 }; diff --git a/examples/Application/IrrigationSimpleLCD/Helpers.h b/examples/Application/IrrigationSimpleLCD/Helpers.h index 87b86d3..ac811a6 100644 --- a/examples/Application/IrrigationSimpleLCD/Helpers.h +++ b/examples/Application/IrrigationSimpleLCD/Helpers.h @@ -13,11 +13,11 @@ void setSystemClock(String date = __DATE__, String time = __TIME__); void statusLCD(); void backlightOff(bool powerDown); -int getAverageInputRead(int pin, size_t loops = 20); +uint16_t getAverageInputRead(int pin, size_t loops = 20); float getAverage05VRead(int pin); -int getMoisturePerc(int pin); +uint8_t getMoisturePerc(int pin); void displayMsg(const String msg, const unsigned timeout = 5000, const unsigned line = 0, const bool clear = true, const bool off = true); extern std::list alarmTabIDs; extern std::list alarmSketchIDs; -extern std::list dataPoints; \ No newline at end of file +extern std::list dataPoints; 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 4cd7937..5d9db8d 100644 --- a/examples/Application/LowPowerDataLogger/Helpers.h +++ b/examples/Application/LowPowerDataLogger/Helpers.h @@ -50,7 +50,7 @@ int getAverageInputRead(int pin, const size_t loops) analogReadResolution(ADC_RESOLUTION); Input.enable(); - for (auto i = 0; i < loops; i++) + for (auto i = 0u; i < loops; i++) tot += Input.analogRead(pin); Input.disable(); @@ -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/0-5V_Input/0-5V_Input.ino b/examples/Basic/0-5V_Input/0-5V_Input.ino index 86cd514..99ff96b 100644 --- a/examples/Basic/0-5V_Input/0-5V_Input.ino +++ b/examples/Basic/0-5V_Input/0-5V_Input.ino @@ -35,8 +35,8 @@ void setup() delay(1000); Serial.println("Hello, Challenge!"); - Power.enable3V3(); - Power.enable5V(); + Power.on(PWR_3V3); + Power.on(PWR_VBAT); Wire.begin(); Expander.begin(); @@ -89,9 +89,9 @@ Voltages getAverageAnalogRead(int pin) int tot { 0 }; - for (auto i = 0; i < loops; i++) + for (auto i = 0u; i < loops; i++) tot += Input.analogRead(pin); - const auto avg = float { tot } * toV / float { loops }; + const auto avg = static_cast(tot) * toV / static_cast(loops); return { avg, avg / rDiv }; } diff --git a/examples/Basic/19V/19V.ino b/examples/Basic/19V/19V.ino index 23aad62..22bd3b1 100644 --- a/examples/Basic/19V/19V.ino +++ b/examples/Basic/19V/19V.ino @@ -18,9 +18,9 @@ void setup() delay(1000); Serial.println("Hello, Challenge!"); - Power.enable3V3(); - Power.enable5V(); - Power.enable19V(); + Power.on(PWR_3V3); + Power.on(PWR_VBAT); + Power.on(PWR_19V); Wire.begin(); Expander.begin(); @@ -60,9 +60,9 @@ Voltages getAverageAnalogRead(int pin) int tot { 0 }; - for (auto i = 0; i < loops; i++) + for (auto i = 0u; i < loops; i++) tot += Input.analogRead(pin); - const auto avg = float { tot } * toV / float { loops }; + const auto avg = static_cast(tot) * toV / static_cast(loops); return { avg, avg / rDiv }; } diff --git a/examples/Basic/4-20mA_Input/4-20mA_Input.ino b/examples/Basic/4-20mA_Input/4-20mA_Input.ino index 74fe6dd..f74c00c 100644 --- a/examples/Basic/4-20mA_Input/4-20mA_Input.ino +++ b/examples/Basic/4-20mA_Input/4-20mA_Input.ino @@ -34,9 +34,9 @@ void setup() delay(1000); Serial.println("Hello, Challenge!"); - Power.enable3V3(); - Power.enable5V(); - Power.enable19V(); + Power.on(PWR_3V3); + Power.on(PWR_VBAT); + Power.on(PWR_19V); Wire.begin(); Expander.begin(); @@ -85,9 +85,9 @@ Voltages getAverageAnalogRead(int pin) int tot { 0 }; - for (auto i = 0; i < loops; i++) + for (auto i = 0u; i < loops; i++) tot += Input.analogRead(pin); - const auto avg = float { tot } * toV / float { loops }; + const auto avg = static_cast(tot) * toV / static_cast(loops); return { avg, avg / rDiv }; } 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/Blink/Blink.ino b/examples/Basic/Blink/Blink.ino index 8ca45e7..366b360 100644 --- a/examples/Basic/Blink/Blink.ino +++ b/examples/Basic/Blink/Blink.ino @@ -20,8 +20,8 @@ void setup() delay(1000); Serial.println("Hello, Challenge!"); - Power.enable3V3(); - Power.enable5V(); + Power.on(PWR_3V3); + Power.on(PWR_VBAT); Wire.begin(); @@ -31,7 +31,7 @@ void setup() if (!Expander.begin()) { Serial.println("failed."); Serial.println("Please, be sure to enable gated 3V3 and 5V power rails"); - Serial.println("via Power.enable3V3() and Power.enable5V()."); + Serial.println("via Power.on(PWR_3V3) and Power.on(PWR_VBAT)."); } Serial.println("succeeded."); 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 9b53cf2..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; @@ -54,11 +56,20 @@ void setup() delay(1000); Serial.println("Testing LCD for Arduino Edge Control"); - Power.enable3V3(); - Power.enable5V(); + Power.on(PWR_3V3); + 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 8959122..86d7ddb 100644 --- a/examples/Basic/Watermark10k/Watermark10k.ino +++ b/examples/Basic/Watermark10k/Watermark10k.ino @@ -10,20 +10,21 @@ void setup() while (!Serial && millis() < startNow) ; + EdgeControl.begin(); delay(2000); Serial.println("Hello, 10k"); - Power.enable3V3(); - Power.enable5V(); + Power.on(PWR_3V3); + 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() @@ -54,10 +54,12 @@ void loop() int wmkAvgAnalogRead(pin_size_t pin) { constexpr size_t count { 10 }; - unsigned int sum; + unsigned int sum { 0 }; - for (auto i = 0; i < count; i ++) + 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/Basic/WatermarkTau/WatermarkTau.ino b/examples/Basic/WatermarkTau/WatermarkTau.ino index fe1e9e4..fc2278a 100644 --- a/examples/Basic/WatermarkTau/WatermarkTau.ino +++ b/examples/Basic/WatermarkTau/WatermarkTau.ino @@ -29,8 +29,8 @@ void setup() ; delay(2000); - Power.enable3V3(); - Power.enable5V(); + Power.on(PWR_3V3); + Power.on(PWR_VBAT); Wire.begin(); Expander.begin(); @@ -67,7 +67,7 @@ void loop() Watermark.commonMode(INPUT); Watermark.calibrationMode(OUTPUT); - for (auto i = 0; i < measuresCount; i++) { + for (auto i = 0u; i < measuresCount; i++) { Watermark.calibrationWrite(HIGH); auto start = micros(); @@ -104,7 +104,7 @@ void loop() Watermark.commonMode(OUTPUT); Watermark.calibrationMode(INPUT); - for (auto i = 0; i < measuresCount; i++) { + for (auto i = 0u; i < measuresCount; i++) { Watermark.commonWrite(HIGH); auto start = micros(); 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/examples/RPC/LORA_EdgeControl/LORA_EdgeControl.ino b/examples/RPC/LORA_EdgeControl/LORA_EdgeControl.ino index c583651..d7701fc 100644 --- a/examples/RPC/LORA_EdgeControl/LORA_EdgeControl.ino +++ b/examples/RPC/LORA_EdgeControl/LORA_EdgeControl.ino @@ -42,7 +42,8 @@ void rpc_retrieve_LoRa_data() if (rpc.call_no_copy_no_args(F("retrieve_msg"), &message, &result_data_len) ) { - char buff[result_data_len + 1]; memset(buff, 0, result_data_len + 1); + char buff[result_data_len + 1]; + memset(buff, 0, result_data_len + 1); // Copy what we received into our data type container. memcpy(buff, message, result_data_len); // Use it now. diff --git a/examples/RPC/RPC_FullDuplex/RPC_FullDuplex.ino b/examples/RPC/RPC_FullDuplex/RPC_FullDuplex.ino deleted file mode 100644 index 03a7f3b..0000000 --- a/examples/RPC/RPC_FullDuplex/RPC_FullDuplex.ino +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -openmv::rpc_scratch_buffer<256> scratch_buffer; -openmv::rpc_callback_buffer<8> callback_buffer; - -// #define I2C_MASTER_UART_SLAVE 1 -#define I2C_SLAVE_UART_MASTER 1 - -#if defined(I2C_SLAVE_UART_MASTER) -openmv::rpc_hardware_serial1_uart_master master(115200); -openmv::rpc_i2c1_slave slave(0x13); -#elif defined(I2C_MASTER_UART_SLAVE) -openmv::rpc_i2c1_master master(0x13, 10000); -openmv::rpc_hardware_serial1_uart_slave slave(115200); -#endif - -constexpr uint32_t requestInterval { 1000 }; -uint32_t requestNow { }; - -void dataReceived(void *in_data, size_t in_data_len) -{ - uint8_t data; - memcpy(&data, in_data, sizeof(data)); - Serial.print("New Data Received: "); - Serial.println(data); -} - -void setup() -{ - EdgeControl.begin(); - - Power.on(PWR_3V3); - Power.on(PWR_VBAT); - - Power.on(PWR_MKR2); - delay(5000); // Wait for MKR2 to power-on - - Serial.begin(115200); - while(!Serial); - master.begin(); - - slave.register_callback("dataReceived", dataReceived); - delay(1000); - slave.begin(); - - requestNow = millis() + requestInterval; -} - -void loop() -{ - slave.loop(10, 10); - - if (millis() > requestNow) { - Serial.println("Requesting Data Upload"); - uint32_t data = micros(); - master.call("sendData", &data, sizeof(data), nullptr, 0, false); - requestNow = millis() + requestInterval; - Serial.println("Data Upload Requested"); - } -} \ No newline at end of file diff --git a/examples/RPC/RPC_HttpGet/RPC_HttpGet.ino b/examples/RPC/RPC_HttpGet/RPC_HttpGet.ino deleted file mode 100644 index fa7bafc..0000000 --- a/examples/RPC/RPC_HttpGet/RPC_HttpGet.ino +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include -#include - -openmv::rpc_scratch_buffer<256> scratch_buffer; -openmv::rpc_hardware_serial1_uart_master rpc(115200); - -constexpr uint32_t requestInterval { 10 * 1000 }; -uint32_t requestNow {}; - -bool ledStatus { false }; - -void setup() -{ - EdgeControl.begin(); - - Power.on(PWR_3V3); - Power.on(PWR_VBAT); - - Power.on(PWR_MKR2); - delay(5000); // Wait for MKR2 to power-on - - Serial.println(EdgeControl.serialNumber()); - - // Init the I2C bus - Wire.begin(); - delay(500); - - // Init the I/O Expander - Serial.print("I/O 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.enable3V3() and Power.enable5V()."); - } - Serial.println("succeeded."); - - // Configure the LED1 pin - Expander.pinMode(EXP_LED1, OUTPUT); - Expander.digitalWrite(EXP_LED1, HIGH); - - - Serial.begin(115200); - while (!Serial) - ; - - rpc.begin(); - - requestNow = millis(); -} - -void loop() -{ - if (millis() > requestNow) { - - call1stCallBack(); - - delay(1000); - - call2ndCallback(); - - requestNow = millis() + requestInterval; - } - - Expander.digitalWrite(EXP_LED1, ledStatus); -} - -void call1stCallBack() -{ - Serial.print("Getting Data - 1st Callback: "); - size_t bufferLen { scratch_buffer.buffer_size() }; - char buffer[bufferLen] {}; - auto ret = rpc.call_no_args("getResponseBodyAlt", buffer, bufferLen, true, 1000, 2500); - if (ret == 0) { - Serial.println("Error"); - return; - } - Serial.print(bufferLen); - Serial.print(" "); - Serial.println(buffer); - JSONVar dweet = JSON.parse(buffer); - String pretty = JSON.stringify(dweet); - Serial.println(dweet["with"][0]["content"]["hello"]); - // Serial.println(dweet["hello"]); -} - -void call2ndCallback() -{ - auto sn = EdgeControl.serialNumber(); - - Serial.print("Getting Data - 2nd Callback: "); - - // size_t bufferAltLen; - // char* bufferAlt; - // auto retAlt = rpc.call_no_copy_no_args("getResponseBodyAlt", (void**)(&bufferAlt), &bufferAltLen, 1000, 2500); - // auto retAlt = rpc.call_no_copy("getResponseBodyArgs", (void *)(sn.c_str()), sn.length(), (void**)(&bufferAlt), &bufferAltLen, 1000, 2500); - - size_t bufferLen { scratch_buffer.buffer_size() }; - char buffer[bufferLen] {}; - auto ret = rpc.call("getResponseBodyArgs", (void *)(sn.c_str()), sn.length(), buffer, bufferLen, false, 1000, 2500); - - if (ret == 0) { - Serial.println("Error"); - return; - } - // Null-terminate the received buffer - // buffer[bufferLen] = 0; - // Serial.print(bufferLen); - // Serial.print(" "); - Serial.println(buffer); - JSONVar dweet = JSON.parse(buffer); - - JSONVar ledCommandJSON = dweet["with"][0]["content"]["hello"]; - String ledCommand = (const char *)ledCommandJSON; - - Serial.println(ledCommand); - - ledStatus = !(ledCommand == "on"); - Serial.println(ledStatus); -} diff --git a/examples/Storage/StoragePartitions/StoragePartitions.ino b/examples/Storage/StoragePartitions/StoragePartitions.ino index 4e19f42..2658f8e 100644 --- a/examples/Storage/StoragePartitions/StoragePartitions.ino +++ b/examples/Storage/StoragePartitions/StoragePartitions.ino @@ -6,6 +6,9 @@ #include #include +#include +using namespace std::chrono_literals; + #include "edge_control_storage_limits.h" using namespace mbed; @@ -95,10 +98,10 @@ void setup() Serial.println("TDB Init " + String(err == 0 ? "OK" : "KO") + " (" + String(err) + ")"); // Store data every 1 second - writer.attach([] { doWrite = true; }, 1.0); + writer.attach([] { doWrite = true; }, 1s); // Display data every 5 seconds - lister.attach([] { doList = true; }, 5.0); + lister.attach([] { doList = true; }, 5s); // Init the RNG srand(t.elapsed_time().count()); 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_Expander.cpp b/src/EdgeControl_Expander.cpp index dd3d575..18f1b88 100644 --- a/src/EdgeControl_Expander.cpp +++ b/src/EdgeControl_Expander.cpp @@ -13,14 +13,14 @@ bool EdgeControl_IOExpanderClass::begin() { - _status3V3 = Power.status3V3(); - _statusVBAT = Power.statusVBat(); + _status3V3 = Power.status(PWR_3V3); + _statusVBAT = Power.status(PWR_VBAT); if(!_status3V3) - Power.enable3V3(); + Power.on(PWR_3V3); if(!_statusVBAT) - Power.enableVBat(); + Power.on(PWR_VBAT); Wire.begin(); diff --git a/src/EdgeControl_Input.cpp b/src/EdgeControl_Input.cpp index 3ac852e..7d61440 100644 --- a/src/EdgeControl_Input.cpp +++ b/src/EdgeControl_Input.cpp @@ -47,7 +47,7 @@ void EdgeControl_InputClass::disable() bool EdgeControl_InputClass::selectSensor(pin_size_t channel) { - if (0 > channel > 15) + if (channel > 15) return false; if (_channel == channel) diff --git a/src/EdgeControl_Latching.cpp b/src/EdgeControl_Latching.cpp index 80a58fd..8b7b458 100644 --- a/src/EdgeControl_Latching.cpp +++ b/src/EdgeControl_Latching.cpp @@ -51,7 +51,7 @@ void EdgeControl_LatchingClass::strobe(unsigned int duration) bool EdgeControl_LatchingClass::selectSensor(pin_size_t channel) { - if (0 > channel > 15) + if (channel > 15) return false; if (_channel == channel) @@ -76,7 +76,7 @@ void EdgeControl_LatchingClass::digitalWrite(pin_size_t pin, PinStatus val) void EdgeControl_LatchingClass::channelDirection(pin_size_t channel, PulseDirection direction) { - PinStatus status; + PinStatus status { LOW }; switch (direction) { case POSITIVE: { @@ -94,4 +94,4 @@ void EdgeControl_LatchingClass::channelDirection(pin_size_t channel, PulseDirect digitalWrite(channel, status); } -EdgeControl_LatchingClass Latching {}; \ No newline at end of file +EdgeControl_LatchingClass Latching {}; diff --git a/src/EdgeControl_Power.cpp b/src/EdgeControl_Power.cpp index e3494f6..f56d6ac 100644 --- a/src/EdgeControl_Power.cpp +++ b/src/EdgeControl_Power.cpp @@ -26,7 +26,7 @@ void EdgeControl_PowerClass::begin() pinMode(VBAT_PROBE, INPUT); - for (auto status : _statuses) + for (auto& status : _statuses) status = false; } @@ -67,15 +67,16 @@ void EdgeControl_PowerClass::set(const PowerRail rail, const bool status) float EdgeControl_PowerClass::getVBat(const int adcResolution) const { - constexpr float vbatVD { 100.0f / (100.0f + 475.0f) }; // Voltage Divider on VBAT_PROBE - float valToV { 3.3f / float { (1 << adcResolution) - 1 } }; + constexpr auto vbatVD { 100.0f / (100.0f + 475.0f) }; // Voltage Divider on VBAT_PROBE + const auto maxVAL { (1 << adcResolution) - 1 }; + float valToV { 3.3f / static_cast(maxVAL) }; constexpr unsigned int count { 10 }; analogReference(V_REF); analogReadResolution(adcResolution); unsigned int val { 0 }; - for (auto i = 0; i < count; i++) { + for (auto i = 0u; i < count; i++) { val += analogRead(VBAT_PROBE); delay(1); } diff --git a/src/EdgeControl_Power.h b/src/EdgeControl_Power.h index 39b406c..581a54e 100644 --- a/src/EdgeControl_Power.h +++ b/src/EdgeControl_Power.h @@ -51,15 +51,15 @@ class EdgeControl_PowerClass { [[deprecated]] inline void disableVBat() { off(PWR_VBAT); }; [[deprecated]] inline bool setVBat(bool st) { set(PWR_VBAT, st); return status(PWR_VBAT); }; - [[deprecated]] inline void enable5V() { enableVBat(); }; - [[deprecated]] inline bool status5V() { return statusVBat(); }; - [[deprecated]] inline void disable5V() { disableVBat(); }; - [[deprecated]] inline bool set5V(bool st) { return setVBat(st); }; + [[deprecated]] inline void enable5V() { on(PWR_VBAT); }; + [[deprecated]] inline bool status5V() { return status(PWR_VBAT); }; + [[deprecated]] inline void disable5V() { off(PWR_VBAT); }; + [[deprecated]] inline bool set5V(bool st) { set(PWR_VBAT, st); return status(PWR_VBAT); }; - [[deprecated]] inline void enable12V() { enableVBat(); }; - [[deprecated]] inline bool status12V() { return statusVBat(); }; - [[deprecated]] inline void disable12V() { disableVBat(); }; - [[deprecated]] inline bool set12V(bool st) { return setVBat(st); }; + [[deprecated]] inline void enable12V() { on(PWR_VBAT); }; + [[deprecated]] inline bool status12V() { return status(PWR_VBAT); }; + [[deprecated]] inline void disable12V() { off(PWR_VBAT);; }; + [[deprecated]] inline bool set12V(bool st) { set(PWR_VBAT, st); return status(PWR_VBAT); }; [[deprecated]] inline void enable3V3() { on(PWR_3V3); }; [[deprecated]] inline bool status3V3() { return status(PWR_3V3); }; @@ -80,4 +80,4 @@ class EdgeControl_PowerClass { bool _statuses[PWR_RAILS_SIZE]; }; -extern EdgeControl_PowerClass Power; \ No newline at end of file +extern EdgeControl_PowerClass Power; 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/EdgeControl_SolidStateRelay.cpp b/src/EdgeControl_SolidStateRelay.cpp index b752584..5df641a 100644 --- a/src/EdgeControl_SolidStateRelay.cpp +++ b/src/EdgeControl_SolidStateRelay.cpp @@ -11,8 +11,9 @@ #include "EdgeControl_SolidStateRelay.h" EdgeControl_SolidStateRelayClass::EdgeControl_SolidStateRelayClass() - : _relaySPI(digitalPinToPinName(CMD_TRIAC_DATA), digitalPinToPinName(CMD_TRIAC_CLK), P1_5) - , _relayPkt() + : _relayPkt() + , _relaySPI(digitalPinToPinName(CMD_TRIAC_DATA), digitalPinToPinName(CMD_TRIAC_CLK), P1_5) + { } @@ -75,4 +76,4 @@ void EdgeControl_SolidStateRelayClass::doSPITransfer() _relaySPI.endTransaction(); } -EdgeControl_SolidStateRelayClass Relay {}; \ No newline at end of file +EdgeControl_SolidStateRelayClass Relay {}; diff --git a/src/EdgeControl_Watermark.cpp b/src/EdgeControl_Watermark.cpp index 094a5fd..db6bf09 100644 --- a/src/EdgeControl_Watermark.cpp +++ b/src/EdgeControl_Watermark.cpp @@ -106,7 +106,7 @@ void EdgeControl_WatermarkClass::setHighPrecision(bool precision) bool EdgeControl_WatermarkClass::selectSensor(pin_size_t channel) { - if (0 > channel > 15) + if (channel > 15) return false; if (_channel == channel) 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]; diff --git a/src/lib/solidstaterelay/TS13102.cpp b/src/lib/solidstaterelay/TS13102.cpp index 59cfea9..0c42eef 100644 --- a/src/lib/solidstaterelay/TS13102.cpp +++ b/src/lib/solidstaterelay/TS13102.cpp @@ -55,10 +55,12 @@ bool TS13102Packet::setCommand(const uint8_t command) void TS13102Packet::toTSBits(const uint8_t n, uint16_t* out, const size_t len) const { + // TODO: convert to a for-loop int i = len; while (i > 0) { - out[len - i--] = (n >> (i - 1)) & 1 ? TS13102_ONE : TS13102_ZERO; + out[len - i] = (n >> (i - 1)) & 1 ? TS13102_ONE : TS13102_ZERO; + i--; } } @@ -134,4 +136,4 @@ size_t TS13102Packet::length() size_t TS13102Packet::lengthWords() { return sizeof(TS13102Packet) / 2; -} \ No newline at end of file +} 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