{"id":20346655,"url":"https://github.com/arthurfdlr/self_balancing_bike","last_synced_at":"2025-08-03T19:07:48.406Z","repository":{"id":112737091,"uuid":"200863118","full_name":"ArthurFDLR/Self_balancing_bike","owner":"ArthurFDLR","description":"Bike stabilized by an inertial wheel controlled by Arduino nano","archived":false,"fork":false,"pushed_at":"2019-09-29T14:29:54.000Z","size":11477,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-14T22:31:39.614Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ArthurFDLR.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-06T14:02:07.000Z","updated_at":"2023-02-26T02:12:50.000Z","dependencies_parsed_at":"2023-09-13T13:16:25.683Z","dependency_job_id":null,"html_url":"https://github.com/ArthurFDLR/Self_balancing_bike","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurFDLR%2FSelf_balancing_bike","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurFDLR%2FSelf_balancing_bike/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurFDLR%2FSelf_balancing_bike/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurFDLR%2FSelf_balancing_bike/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ArthurFDLR","download_url":"https://codeload.github.com/ArthurFDLR/Self_balancing_bike/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241877420,"owners_count":20035403,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T22:13:45.231Z","updated_at":"2025-03-04T15:47:44.514Z","avatar_url":"https://github.com/ArthurFDLR.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Self_balancing_bike\n\nThe final objective is to stabilize a bike using a flywheel. For now, I'm focusing on the stabilisation part : reading IMU data, precise DC motor control, PID controller ...\n\n## Mecanical parts\n### Frame \nI wanted something as simple as possible. I initialy printed a single arm supported wheel. However the mass of the wheel was way to much for the frame to handle. I added a second arm to hold the wheel thanks to a bearing. The height of the rotationnal axis is variable. Once in place, toothpicks lock the position.\n\n### Flywheel\nTheorically I could determine the momentum of the wheel. However the equation depends on way to many factors to be really usable from the ground up. I've simply use an aluminum wheel I had laying around. I'll eventually change it to achieve a better efficiency.\n\n## Electronics\n\nNothing to fancy here. A simple Nano v3 to compute the data, a MD13S motor driver with a Pololu 6V 25mm motor and an MPU6050. I'll certainly swap those componnent for a single board like a Storm32-BGC V1.32 usually used for gimbals. It has all I need (and even more) for this project.\n\n## Code\n\nThe main goal is to get an efficiente code that can run as fast as possible on the Nano. For exemple I access directly to Atmega's registers during ISR. Currently runing at ~60Hz.\nTo ease tunings, a serial communication between the board and the IDE is setup to tune certain values and choose mode in real-time. \n\n| Char command     | Mode          |\n| - | -------------- |\n| 1 | Running stabilisation |\n| 2 | Motor test w/ potentiometer |\n| 3 | Setpoint variation viewer |\n| 4 | IMU data viewer |\n| p | KP tuning |\n| i | KI tuning |\n| d | KD tuning |\n| s | KS tuning |\n\nI use the incredible [library i2cdevlib from jrowberg](https://github.com/jrowberg/i2cdevlib) which takes advantage of the internal DMP of the board to read the IMU.\n\n```c++\n// IN   // NULL\n// OUT  // ypr : float[3]\n// DO   // Read last available data from MPU6050. Update {Yaw,Pitch,Roll} angular position in ypr\nvoid Update_leanAngle();\n\n// IN   // ypr                           : float[3]\n        // IMU_time_now, IMU_time_prev   : uint32_t\n// OUT  // leanAngle                     : float\n        // leanAngle_smoothed            : float\n        // leanAngleError                : float\n        // leanAngle_Integer             : float\n        // leanAngle_derivative          : float\n        // leanAngle_derivative_smoothed : float\n        // leanAngleSetPoint             : float\n// TUNE // leanAngle_Filter              : float\n        // leanAngle_Derivative_Filter   : float\n        // leanAngle_HeavyFilter         : float\n        // setPoint_KP, setPoint_KD      : uint32_t\n// DO   // Calculates lean angle and its derivative and integral from ypr.\n        // Filter results to eliminate noise (exponential filter)\nvoid leanAngle_compute();\n\n// IN   // motorCommandPwm : int16_t\n        // motorSpeedRpm   : uint32_t\n// OUT  // NULL\n// TUNE // motorCommandPwm_Offset         : int16_t\n        // motorCommandPwm_Starter_Offset : int16_t\n        // motorLimitPwm                  : int16_t\n// DO   // Filters command and send to motor. Smooth start, offset, limit ...\nvoid Set_Motor_Speed();\n\n// IN   // motorTickCount    : int32_t\n// OUT  // motorSpeedRpm     : uint32_t\n        // motorDirection    : int8_t\n        // motorAccelerating : bool\n// TUNE // motorFilter : float\n// DO   // Interpret encoder ticks to give motor speed\nvoid Update_MotorData();\n\n// IN   // leanAngleError       : float\n        // leanAngle_Integer    : float\n        // leanAngle_derivative : float\n        // motorDirection       : int8_t\n        // motorSpeedRpm        : uint32_t\n// OUT  // PID_output           : double\n// TUNE // KP, KI, KD, KS       : float\n        // motorFriction        : uint32_t\n        // motorLimitPwm        : int16_t\n// DO   // Compute data to give command w/PID controller\nvoid Update_MotorData();\n```\n\n## Current state\n\n[![IMU data viewer](http://img.youtube.com/vi/QBGMhSDM0Ms/0.jpg)](http://www.youtube.com/watch?v=QBGMhSDM0Ms \"IMU data viewer\")\n\nI didn't find any way to start the motor without it giving a strong hit. It leads to an overshooting when trying to stabilize when the motor is still, for any KP ... I tried to set the standard rotation speed around PWM=40. I achieved some good reaction but only one falling side at a time. The braking power of the motor is way stronger than it's acceleration. It would recquiere an adaptive PID tuning given wheel rotation acceleration sign. Even then, it would be higly unefficient.\nI'm now trying to fit a gimbal brushless motor - 120kv -. With a descent control method, I'll eventually overcome the jerkyness at low speed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farthurfdlr%2Fself_balancing_bike","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farthurfdlr%2Fself_balancing_bike","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farthurfdlr%2Fself_balancing_bike/lists"}