Skip to content

Feature/update fan speeds#30

Open
directvox wants to merge 5 commits into
kartben:masterfrom
directvox:feature/update-fan-speeds
Open

Feature/update fan speeds#30
directvox wants to merge 5 commits into
kartben:masterfrom
directvox:feature/update-fan-speeds

Conversation

@directvox
Copy link
Copy Markdown

Trigger fan speed changes by triggering button A

google-labs-jules Bot and others added 3 commits May 23, 2025 14:56
This commit introduces a multi-speed fan control feature using Button A (WIO_KEY_A).
The fan can now be cycled through four states: Off, Low, Medium, and High.

Changes include:
- Added a new state variable `current_fan_speed_level` to track fan speed.
- Defined PWM constants for Off (0), Low (20), Medium (100), and High (200) speeds.
- Modified `setup()` to initialize the fan to Off using `analogWrite(D0, FAN_PWM_OFF)`.
- Updated `ButtonEventHandler` to handle `WIO_KEY_A` presses:
    - Cycles through Off -> Low -> Medium -> High -> Off states.
    - Uses `analogWrite(D0, ...)` with the respective PWM values.
- Added `WIO_KEY_A` to the `ButtonId` enum and initialized it in `ButtonInit`.
- Commented out the previous simple toggle fan logic associated with Button C to avoid conflicts.
version 8.0.0 not supported anymore
The PWM values for the fan speed control have been updated based on your feedback to provide a different speed curve.

- FAN_PWM_LOW changed from 20 to 100
- FAN_PWM_MEDIUM changed from 100 to 150
- FAN_PWM_HIGH remains at 200
- FAN_PWM_OFF remains at 0

Button A continues to cycle through Off, Low, Medium, and High fan speed states using these new PWM values.
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @directvox, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

Hello team, gemini-code-assist here with a summary of this pull request. This PR, authored by directvox, introduces functionality to control fan speed using Pulse Width Modulation (PWM) via Button A. The previous simple ON/OFF toggle logic on Button C has been commented out in favor of this new, more granular control method. The changes also include an update to a platform dependency version in the project configuration.

Highlights

  • Variable Fan Speed Control: Implements PWM-based fan speed control on pin D0, defining four levels: Off, Low, Medium, and High.
  • Button A Mapping: Maps Button A to cycle through the defined fan speed levels (Off -> Low -> Medium -> High -> Off) upon release.
  • Button C Logic Update: The previous ON/OFF toggle logic for the fan on Button C has been commented out, shifting the primary fan control to Button A.
  • Dependency Update: Updates the atmelsam platform version in the PlatformIO configuration file.

Changelog

  • firmware/platformio.ini
    • Updated the atmelsam platform version from 8.0.0 to 8.3.0 (L12).
    • Removed a trailing newline character at the end of the file (L51).
  • firmware/src/main.cpp
    • Commented out the old fan_state variable and introduced current_fan_speed_level (uint8_t) and constants for PWM values (FAN_PWM_OFF, LOW, MEDIUM, HIGH) to manage variable fan speeds (L288-293).
    • Added ButtonId::A to the ButtonId enumeration (L302).
    • Modified the ButtonEventHandler to handle the kEventReleased event for ButtonId::A, implementing the logic to cycle through fan speed levels using analogWrite (L350-364).
    • Commented out the previous fan toggle logic associated with ButtonId::C (L369-374).
    • Added initialization for Button A in the ButtonInit function (L407-408).
    • Changed the initial fan state setup in setup() to use analogWrite(D0, FAN_PWM_OFF) instead of the old digitalWrite method (L466).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


Button A is pressed,
Fan speed cycles, low to high,
Cool breeze starts to blow.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully implements the feature to control the fan speed using Button A, cycling through Off, Low, Medium, and High settings. The changes involve updating the platform version, adding new constants for PWM values, introducing a state variable for the fan speed level, and modifying the button event handler to manage the fan speed based on Button A presses. The old fan toggle logic on Button C has been commented out, which is a good temporary measure to avoid conflicts.

The use of constants for the PWM values is a good practice for readability and maintainability. The logic for cycling through the speeds appears correct. Overall, the core functionality requested in the PR description is implemented.

Summary of Findings

  • Fan speed control logic verbosity: The if/else if/else structure for cycling through fan speeds is functional but could be simplified using an array and modulo for better maintainability and extensibility.
  • Hardcoded fan pin: The pin D0 used for fan control is hardcoded in multiple places. Defining a constant for this pin would improve maintainability.
  • Commented-out code: The old fan toggle logic for Button C is commented out. While this is fine as a temporary measure, it should ideally be removed in a subsequent cleanup PR.
  • Trailing newline in platformio.ini: A trailing newline was removed from the platformio.ini file. This is a minor stylistic change.

Merge Readiness

The pull request implements the core functionality as described and introduces several positive changes like using constants for PWM values. There are a couple of medium-severity maintainability issues related to the fan speed control logic structure and the hardcoded pin number. I recommend addressing these suggestions to improve the code's maintainability before merging. I am unable to approve this pull request; please have other reviewers approve this code before merging.

Comment thread firmware/src/main.cpp
Comment on lines +351 to +364
if (static_cast<ButtonId>(id) == ButtonId::A) {
if (current_fan_speed_level == 0) { // Currently Off
current_fan_speed_level = 1; // Set to Low
analogWrite(D0, FAN_PWM_LOW);
} else if (current_fan_speed_level == 1) { // Currently Low
current_fan_speed_level = 2; // Set to Medium
analogWrite(D0, FAN_PWM_MEDIUM);
} else if (current_fan_speed_level == 2) { // Currently Medium
current_fan_speed_level = 3; // Set to High
analogWrite(D0, FAN_PWM_HIGH);
} else { // Currently High (or any other state, cycle back to Off)
current_fan_speed_level = 0; // Set to Off
analogWrite(D0, FAN_PWM_OFF);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for cycling through the fan speed levels using a series of if/else if/else statements is functional but can become verbose if more speed levels are added. Consider using an array of PWM values and a modulo operator to cycle through the levels, which can make the code more concise and easier to extend.

Suggested change
if (static_cast<ButtonId>(id) == ButtonId::A) {
if (current_fan_speed_level == 0) { // Currently Off
current_fan_speed_level = 1; // Set to Low
analogWrite(D0, FAN_PWM_LOW);
} else if (current_fan_speed_level == 1) { // Currently Low
current_fan_speed_level = 2; // Set to Medium
analogWrite(D0, FAN_PWM_MEDIUM);
} else if (current_fan_speed_level == 2) { // Currently Medium
current_fan_speed_level = 3; // Set to High
analogWrite(D0, FAN_PWM_HIGH);
} else { // Currently High (or any other state, cycle back to Off)
current_fan_speed_level = 0; // Set to Off
analogWrite(D0, FAN_PWM_OFF);
}
if (static_cast<ButtonId>(id) == ButtonId::A) {
const int fan_pwm_levels[] = {FAN_PWM_OFF, FAN_PWM_LOW, FAN_PWM_MEDIUM, FAN_PWM_HIGH};
const int num_levels = sizeof(fan_pwm_levels) / sizeof(fan_pwm_levels[0]);
current_fan_speed_level = (current_fan_speed_level + 1) % num_levels;
analogWrite(D0, fan_pwm_levels[current_fan_speed_level]);
}
// Handle other buttons

Comment thread firmware/src/main.cpp
Comment on lines +354 to +363
analogWrite(D0, FAN_PWM_LOW);
} else if (current_fan_speed_level == 1) { // Currently Low
current_fan_speed_level = 2; // Set to Medium
analogWrite(D0, FAN_PWM_MEDIUM);
} else if (current_fan_speed_level == 2) { // Currently Medium
current_fan_speed_level = 3; // Set to High
analogWrite(D0, FAN_PWM_HIGH);
} else { // Currently High (or any other state, cycle back to Off)
current_fan_speed_level = 0; // Set to Off
analogWrite(D0, FAN_PWM_OFF);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The pin D0 is hardcoded here. While common in small embedded projects, defining a constant for the fan control pin would improve maintainability and make it easier to change the pin if needed in the future.

Suggested change
analogWrite(D0, FAN_PWM_LOW);
} else if (current_fan_speed_level == 1) { // Currently Low
current_fan_speed_level = 2; // Set to Medium
analogWrite(D0, FAN_PWM_MEDIUM);
} else if (current_fan_speed_level == 2) { // Currently Medium
current_fan_speed_level = 3; // Set to High
analogWrite(D0, FAN_PWM_HIGH);
} else { // Currently High (or any other state, cycle back to Off)
current_fan_speed_level = 0; // Set to Off
analogWrite(D0, FAN_PWM_OFF);
analogWrite(FAN_PIN, FAN_PWM_LOW);
} else if (current_fan_speed_level == 1) { // Currently Low
current_fan_speed_level = 2; // Set to Medium
analogWrite(FAN_PIN, FAN_PWM_MEDIUM);
} else if (current_fan_speed_level == 2) { // Currently Medium
current_fan_speed_level = 3; // Set to High
analogWrite(FAN_PIN, FAN_PWM_HIGH);
} else { // Currently High (or any other state, cycle back to Off)
current_fan_speed_level = 0; // Set to Off
analogWrite(FAN_PIN, FAN_PWM_OFF);

Comment thread firmware/src/main.cpp

pinMode(D0, OUTPUT);
digitalWrite(D0, INITIAL_FAN_STATE);
analogWrite(D0, FAN_PWM_OFF);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the previous comment, the pin D0 is hardcoded here. Using a constant for the fan pin would be beneficial for maintainability.

Suggested change
analogWrite(D0, FAN_PWM_OFF);
analogWrite(FAN_PIN, FAN_PWM_OFF);

Adds the capability to send sensor data collected in TRAINING mode to the Edge Impulse ingestion API.

Key features and changes:
- Data is sent in batches (default 100 readings).
- Each reading is collected at a 100ms interval.
- Payloads are signed using HMAC SHA256.
- Edge Impulse API Key is configured via `Config.h` (`EDGE_IMPULSE_API_KEY`).
- Edge Impulse HMAC Secret Key is configurable via the serial menu (`set_ei_hmackey`) and stored in flash.
- Other Edge Impulse settings (Device ID, Device Type, Label, Host, Path, Batch Size, Interval) are defined in `Config.h`.
- JSON payload adheres to the Edge Impulse data ingestion format, including `protected` header with `iat` and `signature`.
- Uses `HTTPClient` for secure POST requests to the Edge Impulse API.
- Includes error handling and logging for the ingestion process.
- New utility `CryptoUtils` for HMAC SHA256 computation using mbedTLS.
- Updates to `Storage` and `ConfigurationMode` to support HMAC key management.
Corrects a compilation error in `processAndSendEdgeImpulseBatch`
where `String(iat_timestamp)` was ambiguous because `iat_timestamp`
is a `uint64_t`.

Changed the code to explicitly cast `iat_timestamp` to `unsigned long`
when constructing the filename string:
`String((unsigned long)iat_timestamp)`
This resolves the compiler ambiguity.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant