{"id":17077826,"url":"https://github.com/reinderien/capmeter","last_synced_at":"2025-03-23T12:18:02.403Z","repository":{"id":69225830,"uuid":"105215239","full_name":"reinderien/capmeter","owner":"reinderien","description":"Arduino Mega capacitance meter","archived":false,"fork":false,"pushed_at":"2018-11-06T16:58:20.000Z","size":61,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-28T18:31:16.663Z","etag":null,"topics":["arduino","arduino-mega","c","capacitance","capacitance-meter","electronics"],"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/reinderien.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":"2017-09-29T01:19:44.000Z","updated_at":"2023-10-22T21:04:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"f790cc76-25d1-45bf-a1d9-6ac656fd9022","html_url":"https://github.com/reinderien/capmeter","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/reinderien%2Fcapmeter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reinderien%2Fcapmeter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reinderien%2Fcapmeter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reinderien%2Fcapmeter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reinderien","download_url":"https://codeload.github.com/reinderien/capmeter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245097834,"owners_count":20560319,"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":["arduino","arduino-mega","c","capacitance","capacitance-meter","electronics"],"created_at":"2024-10-14T12:17:10.003Z","updated_at":"2025-03-23T12:18:02.372Z","avatar_url":"https://github.com/reinderien.png","language":"C++","readme":"Introduction\n============\n\nThis is a basic capacitance meter for use with the Arduino.\n\nThis capacitance meter is designed to be extremely cheap and quick to set up. As\nsuch, it's not very accurate or stable, but it works. It has also been designed\nto be battery-friendly, taking advantage of several power-saving options in the\nAVR hardware. It does not use an integrated display; it uses your laptop to show\noutput. It could be adapted to use a battery pack and an integrated display, or\ncould be used as-is with a small tablet or cell phone capable of hosting USB\nserial TTY devices.\n\nRelated Work\n------------\n\nSetups such as that of\n[Jonathan Nethercott](http://wordpress.codewrite.co.uk/pic/2014/01/25/capacitance-meter-mk-ii)\nhave both advantages and disadvantages compared to this one. The main advantage\nwith his is that fewer external parts are required. Disadvantages include \npoorer resolution.\n\n[Nick Gammon](http://www.gammon.com.au/forum/?id=12075) and\n[Circuit Basics](http://www.circuitbasics.com/how-to-make-an-arduino-capacitance-meter)\nhave yet more variants.\n\nThe design presented below pays a little more attention to hardware specific to\nthe AT2560, and uses fairly little Arduino helper library code.\n\nSetup\n=====\n\n1. Connect the three resistors between pins 5/A0/A1/A2 as shown below. If you\n   don't have exact values, you can substitute, but you need to modify the range\n   struct as necessary.\n2. Install the latest version of the Arduino IDE.\n3. Copy and paste the code into it.\n4. Connect your Arduino over USB.\n5. Select the appropriate port and board.\n6. Upload the code.\n\nA note on connections\n---------------------\nFor all connections try to use relatively short jumpers. A breadboard will\nwork, but a project board with soldered connections (especially a proper\n\"shield\"-style board) will introduce less parasitic capacitance. Parasitic or\nstray elements are not fatal, but will inflate measurements in the pF range.\nThe board partially accommodates for this with the zeroing feature.\n\nPortability\n-----------\nThis has been written for the Arduino Mega 2560, the only Arduino sitting in my\ntoolbox. This is definitely overkill. It should be possible to port to other\nAVR-based Arduino systems, such as the Arduino Uno based on the ATmega328P,\nbecause it shares all of the same comparator and capture functionality. The\nfollowing registers are used in the Mega code but missing in the Uno, and would\nrequire removal or replacement:\n\n    COM1C0 COM3A0 COM3B0 COM3C0 CS30 DDRA DDRE DDRF DDRG DDRH DDRJ DDRK DDRL\n    ICES3 ICNC3 MUX5 OCIE1C OCIE3A OCR3A PORTA PORTE PORTF PORTG PORTH PORTJ\n    PORTK PORTL PRR0 PRR1 PRTIM3 TCCR3A TCCR3B TIMSK3 WGM30 WGM32\n\nI'd be happy to write a port for anyone who sends me the hardware. I also take\npull requests for ports.\n\nUsage\n=====\n1. Remove any existing capacitors from the measurement pins before boot (or\n   reboot), while leaving attached any leads you anticipate using to connect to\n   capacitors.\n2. Connect your Arduino over USB.\n3. Select the appropriate port and board.\n4. Start the Arduino IDE's Serial Monitor. Set the monitor to 115200 baud.\n5. Observe as the meter zeroes itself. My unloaded capacitance is usually about\n   50pF.\n6. Connect the capacitor to be measured as shown below.\n7. Observe as the meter converges on a capacitance value. Switching between\n   large and small capacitors will take a few iterations for the auto-range to\n   kick in completely.\n\nDesign\n======\n\nSchematic\n---------\n             | Arduino Mega\n             | 2560 Rev2\n             |\n             | Arduino AVR\n             | Pin     Pin      Function    I/O\n             |\n    ---------| 5V      VCC      drive       out\n    |        |\n    == C     |\n    |        |\n    |--------|  5      PE3/AIN1 -comptor    in\n    |        |\n    |-270R---| A0      PF0      (dis)charge out or Z\n    |--15k---| A1      PF1      (dis)charge out or Z\n    |---1M---| A2      PF2      (dis)charge out or Z\n             |\n             |  0      PE0/RXD0 UART rx     in\n             |  1      PE1/TXD0 UART tx     out\n             |\n             | 13      PB7      LED         out\n\nCalculations\n------------\n\nDigital I/O pins are 5V.\nUsing an internal reference voltage of 1.1V for the comparator, the capture time\nto charge in tau-units is:\n\n\u003cimg src=\"https://latex.codecogs.com/gif.latex?\\frac%7Bt_%7Bfall%7D%7D\\tau=ln\\left(\\frac%7B5%7D%7B1.1%7D\\right)\\approx1.514\"\ntitle=\"tfall/tau = ln(5/1.1) ~ 1.514\" /\u003e\n\nHigher R slows down charge for small capacitance.\nLower R is necessary to speed up charge for high capacitance.\nToo fast, and max capacitance will suffer.\nToo slow, and update speed will suffer.\nMinimum R is based on the max pin \"test\" current of 20mA (absolute max 40mA).\n\n\u003cimg src=\"https://latex.codecogs.com/gif.latex?\\frac%7B5V%7D%7B20mA%7D=250\\Omega\\approx270\\Omega\"\ntitle=\"5V/20mA = 250R ~ 270R\" /\u003e\n\nChoose maximum R based on the impedance of the pins and susceptibility to noise.\nThe ATMega specsheet lists a leakage current of up to 1μA at 5.5V, equivalent to\na minimum input impedance of 5.5MΩ - so a drive resistor anywhere above 1MΩ\ndoesn't work well.\n\nFor good range coverage, having an intermediate resistor is useful. This\nresistor should be close to the geometric mean of the other two:\n\n\u003cimg src=\"https://latex.codecogs.com/gif.latex?\\sqrt%7B1M\\Omega\\cdot270\\Omega%7D\\approx16.43k\\Omega\\approx15k\\Omega\"\ntitle=\"sqrt(1M*270) ~ 16.43k ~ 15k\" /\u003e\n\nBoard has a 16MHz xtal connected to XTAL1/2. Timer 1 is 16-bit.\nWe can switch between prescalers of 1, 8, 64, 256 and 1024 based on capacitance.\n\nThe maximum capacitance measured is when R is minimal, the prescaler is maximal,\nand the timer value is maximal:\n\n\u003cimg src=\"https://latex.codecogs.com/gif.latex?\\frac%7B2^%7B16%7D\\cdot1024%7D%7B16\\textup%7BMHz%7D\\cdot270\\Omega\\cdot%20ln(5/1.1)%7D\\approx10\\textup%7BmF%7D\"\ntitle=\"2^16*1024/16MHz/270/ln(5/1.1) ~ 10mF\" /\u003e\n\nWe don't want to go too much higher, because that will affect the refresh rate\nof the result. We can improve discharge speed by decreasing R, but it cannot go\nso low that the current exceeds the pin max.\n\nIdeally, we would allow the capacitor to fully discharge between each\nmeasurement. Currently, the refresh time is hard-coded at 500ms, so for \ndischarge to 1% or better, the measured capacitor would be at most:\n\n\u003cimg src=\"http://latex.codecogs.com/gif.latex?%5Cfrac%7B0.5s%7D%7B-ln%281%5C%25%29%5Ccdot270%5COmega%7D%5Capprox402%5Cmu%20F\"\ntitle=\"0.5s/-ln(1%)/270 ~ 402uF\" /\u003e\n\nThe theoretical minimum capacitance is when R is maximal, the prescaler is\nminimal, and the timer value is minimal:\n\n\u003cimg src=\"https://latex.codecogs.com/gif.latex?\\frac%7B1%7D%7B16\\textup%7BMHz%7D\\cdot1M\\Omega\\cdot%20ln\\left(5/1.1\\right)%7D\\approx0.04\\textup%7BpF%7D\"\ntitle=\"1/16MHz/1M/ln(5/1.1) ~ 0.04pF\" /\u003e\n\nbut practical limitations of this hardware will not do anything useful for such\na small capacitance. Parasitics alone are much higher than that. Just plugging a\nwire into my breadboard introduced 10pF, and my typical unloaded capacitance is\n50pF.\n\nTo determine when to switch ranges, aim for a charge timer that runs up to\nsomewhere near the 16-bit capacity to get decent resolution, choosing a good\ncombination of R and prescaler.\n\nFor more justification of the range choices, run range-analysis.r and check out\nthe graphs it produces.\n\nReference links\n---------------\n\n[Store](https://store.arduino.cc/usa/arduino-mega-2560-rev3) - This sells the\nrev3, but I have a rev2.\n\n[Board](https://www.arduino.cc/en/uploads/Main/arduino-mega2560-schematic.pdf) -\nThis is the R1 schematic. My R2 is closer to the R1 than the R3. The R3 was\nreleased in Nov 2011.\n\n[API](https://www.arduino.cc/en/Reference/HomePage)\n\n[Chip brief](http://www.microchip.com/wwwproducts/en/ATmega2560)\n\n[Chip spec](http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf)\n\nCompilation notes\n-----------------\n\nThe actual entry point is main() in here (ignoring the bootloader):\n\n[hardware/arduino/avr/cores/arduino/main.cpp](https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/main.cpp)\n\nThe include chain is:\n\n* Arduino.h\n  * [avr/io.h](https://github.com/vancegroup-mirrors/avr-libc/blob/master/avr-libc/include/avr/io.h)\n    * [avr/sfr_defs.h](https://github.com/vancegroup-mirrors/avr-libc/blob/master/avr-libc/include/avr/sfr_defs.h)\n      ; based on -mmcu=atmega2560, \\_\\_AVR_ATmega2560\\_\\_ is defined\n    * [avr/iom2560.h](https://github.com/vancegroup-mirrors/avr-libc/blob/master/avr-libc/include/avr/iom2560.h)\n      * [avr/iomxx0\\_1.h](https://github.com/vancegroup-mirrors/avr-libc/blob/master/avr-libc/include/avr/iomxx0_1.h) -\n        this has most of the interesting SFR defs\n      \nWe need to use a lot of the SFRs directly.\n\nWhen using tools such as avr-objdump, the architecture should be avr:6, and\nsince link-time optimization is enabled, don't dump the .o; dump the .elf.\nSomething like:\n\n    avr-objdump -D -S capmeter.ino.elf \u003e capmeter.asm\n\nTodo\n----\n\n* Maybe disable the comparator via ACSR.ACD between measurements to save power -\n  currently won't work\n* Maybe tweak the autorange algo or enable \"fast\" - currently barfs sometimes\n* Dynamic refresh rate using OC3 based on capacitance and discharge minima\n\nDiscuss\n=======\n\n[![Join the chat at https://gitter.im/capmeter/Lobby](https://badges.gitter.im/capmeter/Lobby.svg)](https://gitter.im/capmeter/Lobby?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freinderien%2Fcapmeter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freinderien%2Fcapmeter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freinderien%2Fcapmeter/lists"}