{"id":21275433,"url":"https://github.com/tmsmr/cm4iofan","last_synced_at":"2025-07-20T12:32:44.065Z","repository":{"id":46405346,"uuid":"417202823","full_name":"tmsmr/cm4iofan","owner":"tmsmr","description":"Simple utility to get/set the PWM duty cycle and to measure the RPM for a fan connected to the 4-pin header on the CM4IO.","archived":false,"fork":false,"pushed_at":"2021-11-27T16:53:32.000Z","size":11546,"stargazers_count":5,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-25T01:49:21.528Z","etag":null,"topics":["compute-module-4","emc2301","golang"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tmsmr.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-14T16:22:58.000Z","updated_at":"2022-03-31T18:24:09.000Z","dependencies_parsed_at":"2022-08-27T06:10:22.130Z","dependency_job_id":null,"html_url":"https://github.com/tmsmr/cm4iofan","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/tmsmr/cm4iofan","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmsmr%2Fcm4iofan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmsmr%2Fcm4iofan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmsmr%2Fcm4iofan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmsmr%2Fcm4iofan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tmsmr","download_url":"https://codeload.github.com/tmsmr/cm4iofan/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmsmr%2Fcm4iofan/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266127212,"owners_count":23880420,"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":["compute-module-4","emc2301","golang"],"created_at":"2024-11-21T09:31:33.007Z","updated_at":"2025-07-20T12:32:44.044Z","avatar_url":"https://github.com/tmsmr.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cm4iofan\n*Simple utility to get/set the PWM duty cycle and to measure the RPM for a fan connected to the 4-pin header on the CM4IO.*\n\n## Requirements\n- Enabled `i2c_vc` overlay (`dtparam=i2c_vc=on` in `/boot/config.txt`)\n- Loaded `i2c-dev` module (e.g. `modprobe i2c-dev` or using `/etc/modules`)\n- A user in the `i2c` group (or `root`)\n\n## Using the Go Module\n\n```go\nimport \"github.com/tmsmr/cm4iofan\"\n \n...\n\nctrl, err := cm4iofan.New()\nif err != nil {\n\tpanic(err)\n}\nerr = ctrl.SetDutyCycle(50)\nif err != nil {\n\tpanic(err)\n}\n```\n\n## Using `fanctl`\n- Build with `cd fanctl \u0026\u0026 go build`.\n- For every tagged version of the Go Module, the `fanctl` utility is built in a GitHub Action (Available on the Releases page).\n\n```shell\n$ fanctl set 50\n$ fanctl get\n50\n$ fanctl rpm\n2623\n```\n\n## POC with thermal monitoring\nYou may use https://github.com/tmsmr/chilld as thermal controller on your Raspberry Pi Compute Module 4 IO Board.\n\n## Comments\n\n### Direct Setting mode vs. Fan Speed Control mode\nThe EMC2301 has a built-in closed loop Fan Speed Control algorithm (Besides many awesome features), that allows the user to select a target RPM which is controlled by a PID.\nI opted for the Direct Setting mode, because it feels more natural to me (Yes, i know that duty cycle/RPM is far from linear...).\n\n### Should i use this for my 24/7-running project?\nIf you want nothing but a reliable/automatic cooling solution for your CM4IO, you should probably go with something like https://github.com/neg2led/cm4io-fan.\n\nThere are scenarios where this Module might be handy (Well, that's why i built it...). But keep in mind, all you do with it, is setting the fan's PWM signal:\n- Some fans won't stop with 0% duty cycle.\n- Most fans will stall with a low duty cycle.\n- ...\n\n### TACH to RPM conversion\nUnfortunately it is not possible to detect RPM's lower than 500 using the EMC2301. That's why the RPM measurement returns a `RPMResult`:\n\n```go\ntype RPMResult struct {\n    Rpm int\n    Stopped bool\n    Undef bool\n}\n```\n\n- When the PWM duty cycle is set to 0%, `Stopped` is `true`. This is only true for fans that are able to stop completely!\n- When the calculated RPM is below 500 (smallest value could be 480), it is not possible to determine the real RPM. In this case `Undef` is `true`.\n\n### On poles, edges and ranges...\nThe EMC2301 may be used to control a wide variety of PWM fans. TACH measurement works different based on the fan's design type (emc2301.pdf: 4.4 Tachometer Measurement).\n\nNoctua's PWM specification states that (regardless of the actual motor design) the tachometer always pulses two times per revolution (Emulating a fan with 2 poles). I **think** this is true for other regular, modern PWM fans. That's why i settled with the following values for the RPM calculation:\n- *poles = 2*\n- *n = 5*\n\nSince i wanted to measure RPM's as low as possible, *RANGE[1:0]* is set to 500 RPM. This means the TACH multiplier is *m = 1*.\n\nUsing these values, a simplified formula for TACH conversion can be used (emc2301.pdf: EQUATION 4-3).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmsmr%2Fcm4iofan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftmsmr%2Fcm4iofan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmsmr%2Fcm4iofan/lists"}