
Ergonomic Split Keyboard
This project involves creating a split 58 key keyboard that quells some of the health detriments of normal keyboards. Fully from scratch!
Components and Skills
- Fusion 360 – Design and 3D Modeling
- Arduino & Firmware – Programming a keyboard from scratch
- Product design – Designing a user-friendly product
- Electrical Engineering – PCB Design and Soldering Components
Design and 3D Modeling
For this project, I primarily used Fusion 360 and 3D printing to construct the framework of my design. The structure was engineered to secure all key electronic components and partially enclose the power unit. Utilizing Fusion 360 enabled me to create highly accurate models that allowed for straightforward assembly, with friction fittings often replacing the need for screws or bolts. Transitioning from TinkerCad to Fusion 360 for this endeavor gave me the opportunity to produce a more thoroughly planned and detailed design, tailored specifically for the electronics involved. This was my first experience using Fusion 360, and I found the process engaging, informative and fun.
Attached Below are some images of my models that I made with Fusion




Arduino Code
For the Code, I learnt how to write code in C++, Arduino uses a slightly simplified version of C++ for its logic. I decided to code 2 versions of the logic: one that checks on the soil moisture content every 15 minutes, and will water it if it’s below the optimal threshold of 600-700; and another that will just water it every 30 minutes no matter what.
Show Arduino Code
// Pins#define IN3_PIN 6 // L298N IN3#define IN4_PIN 4 // L298N IN4#define ENB_PIN 3 // L298N ENB (PWM)#define SOIL_SENSOR_PIN A0// Settingsconst unsigned long CHECK_INTERVAL = 15UL * 60UL * 1000UL; // 15 minutes in msconst unsigned long WATER_DURATION = 150UL * 1000UL; // 2.5 minutes in ms (150000 ms)const int MOISTURE_THRESHOLD = 600; // ideal soil moisture content// Stateunsigned long lastCheckTime = 0;bool watering = false;unsigned long wateringStartTime = 0;void setup() { pinMode(IN3_PIN, OUTPUT); pinMode(IN4_PIN, OUTPUT); pinMode(ENB_PIN, OUTPUT); pinMode(SOIL_SENSOR_PIN, INPUT); Serial.begin(9600);}void startPump() { digitalWrite(IN3_PIN, HIGH); digitalWrite(IN4_PIN, LOW); analogWrite(ENB_PIN, 255); // full speed}void stopPump() { analogWrite(ENB_PIN, 0); digitalWrite(IN3_PIN, LOW); digitalWrite(IN4_PIN, LOW);}void loop() { unsigned long now = millis(); // If currently watering, check if time is up if (watering) { if (now - wateringStartTime >= WATER_DURATION) { stopPump(); watering = false; Serial.println("Watering finished"); } // while watering, just exit loop() return; } // Not watering: check if it's time for a new moisture check if (now - lastCheckTime >= CHECK_INTERVAL) { lastCheckTime = now; int moistureValue = analogRead(SOIL_SENSOR_PIN); Serial.print("Moisture check: "); Serial.println(moistureValue); if (moistureValue > MOISTURE_THRESHOLD) { // dry -> start watering Serial.println("Soil dry, starting pump"); startPump(); watering = true; wateringStartTime = now; } else { Serial.println("Soil wet enough, no watering"); } }}/*unsigned long lastWaterStart = 0;bool watering = false;void setup() { pinMode(IN3_PIN, OUTPUT); pinMode(IN4_PIN, OUTPUT); pinMode(ENB_PIN, OUTPUT); Serial.begin(9600);}void startPump() { digitalWrite(IN3_PIN, HIGH); digitalWrite(IN4_PIN, LOW); analogWrite(ENB_PIN, 255);}void stopPump() { analogWrite(ENB_PIN, 0); digitalWrite(IN3_PIN, LOW); digitalWrite(IN4_PIN, LOW);}void loop() { unsigned long now = millis(); if (watering) { if (now - lastWaterStart >= WATER_DURATION) { stopPump(); watering = false; Serial.println("Water OFF"); } return; } // Not watering: wait for next interval if (now - lastWaterStart >= WATER_INTERVAL) { startPump(); lastWaterStart = now; watering = true; Serial.println("Water ON"); }}*/