{"id":15495562,"url":"https://github.com/coddingtonbear/bullion","last_synced_at":"2025-03-28T17:15:24.818Z","repository":{"id":145176310,"uuid":"79074895","full_name":"coddingtonbear/bullion","owner":"coddingtonbear","description":"USB \u0026 SPI Interface for FS9721-based Multimeters (TP4000ZC)","archived":false,"fork":false,"pushed_at":"2017-02-20T07:12:18.000Z","size":119,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-19T12:38:16.308Z","etag":null,"topics":["arduino","atmega328pb","avr","hardware","hardware-designs","microcontroller","multimeter","pcb","spi","spi-interface"],"latest_commit_sha":null,"homepage":"","language":"KiCad","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/coddingtonbear.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-01-16T02:20:22.000Z","updated_at":"2024-08-28T23:25:35.000Z","dependencies_parsed_at":"2023-03-23T18:18:14.510Z","dependency_job_id":null,"html_url":"https://github.com/coddingtonbear/bullion","commit_stats":{"total_commits":18,"total_committers":1,"mean_commits":18.0,"dds":0.0,"last_synced_commit":"be69af80abb5c6be3418a3a4b0ca9cb127772e6a"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coddingtonbear%2Fbullion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coddingtonbear%2Fbullion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coddingtonbear%2Fbullion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coddingtonbear%2Fbullion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coddingtonbear","download_url":"https://codeload.github.com/coddingtonbear/bullion/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246068305,"owners_count":20718503,"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","atmega328pb","avr","hardware","hardware-designs","microcontroller","multimeter","pcb","spi","spi-interface"],"created_at":"2024-10-02T08:17:43.411Z","updated_at":"2025-03-28T17:15:24.795Z","avatar_url":"https://github.com/coddingtonbear.png","language":"KiCad","funding_links":[],"categories":[],"sub_categories":[],"readme":"# USB \u0026 SPI Interface for FS9721-based Multimeter (Bullion)\n\n![](https://coddingtonbear-public.s3.amazonaws.com/github/bullion/connected.jpg)\n\nDo you have a cheap Chinese multimeter using the FS9721 chipset and\nwant to add an easy-to-use USB interface to it?  Or, do you have an\narduino project in mind where you might want to collect measurements\nfrom your multimeter?  This project can help you do both of those things.\n\n## Compatible Multimeters\n\nAny multimeter using the FS9721 chipset is compatible, but you may have\nto adapt the hardware design herein if your multimeter does not have a\n3.5mm stereo jack labeled \"RS232\".\n\nKnown-compatible multimeters include:\n\n* **RECOMMENDED** [TekPower TP4000ZC](https://www.amazon.com/Tekpower-TP4000ZC-Interfaced-Multimeter-Computer/dp/B000OPDFLM)\n    * Also available as the Digitek DT-4000ZC.\n    * Includes a 3.5mm RS232 port.\n* [Mastech V\u0026A 18B](https://www.amazon.com/Manual-Ranging-Digital-Multimeter-Interface/dp/B000LQONYM)\n    * Does have an external RS232 port, but it is not compatible with the\n      hardware files you'll find herein.  You will have to improvise.\n* [UNI-T UT60E](https://www.amazon.com/UNI-T-UT60E-Precise-Light-Weight/dp/B0152OJAWC)\n    * Does have an external RS232 port, but it is not compatible with the\n      hardware files you'll find herein.  You will have to improvise.\n\n## Interfaces\n\n### USB\n\n* Baud Rate: 2400\n\nWhen connected to your PC, the device will appear as an additional serial\nport (may require installation of a driver for the CH340G USB UART\nchip).\n\nBy default, the raw output from the Multimeter will be displayed\nas new multimeter data is received in a way identical to that of what the\nbuilt-in serial port would output were you to connect it directly to your\ncomputer, but you can select a variety of output formats using the below\ncommands.\n\n#### Commands\n\nCommands are sent in the format `COMMAND=VALUE` followed by a single\nnewline character.\n\n* Command ``output``:\n    * Value ``raw`` (*default*): Display raw bytes received from multimeter.\n    * Value ``value``: Display actual value scaled to base unit.\n    * Value ``displayed``: Display displayed value.  Note that this is\n      not scaled to the base unit.  Use the ``unit`` command below to\n      determine magnitude.\n    * Value ``none``: Disable output.\n* Command ``units``:\n    * Value ``0`` (*default*): Do not print unit.\n    * Value ``1``: Print unit.  If the value is not scaled to the base\n      unit, this may include an SI magnitude prefix ('u', 'n, 'm', 'k', 'M').\n\n**Note**: *Command output is not displayed until you press \u003cENTER\u003e*\n\nFor example; to display units in the format they are displayed on the screen,\nyou could send the following two commands:\n\n```\noutput=displayed\nunits=1\n```\n\nand you would, assuming you were measuring a voltage source, receive responses like:\n\n```\n1.244 mV\n1.239 mV\n```\n\nBut, if you wanted to output values scaled to their base unit so programs\nconsuming these values wouldn't need to worry about the SI magnitude, you\ncould instead send the following commands:\n\n```\noutput=value\nunits=1\n```\n\nand you'd receive the following values:\n\n```\n0.001244 V\n0.001239 V\n```\n\nYou could even turn off unit display if you were not concerned about\nidentifying what mode the multimeter was in while the returned measurement\nwas taking place (note, though, that `units=0` is the default state, so\nyou need not send that command if you have not already enabled unit display):\n\n```\noutput=value\nunits=0\n```\n\nand then you'd receive very easy-to-parse values:\n\n```\n0.001244\n0.001239\n```\n\n### SPI\n\nEvery SPI transaction is a single 8-bit command ID, followed by a\n32-bit response.\n\nThe following commands are implemented:\n\n* `0x01`: Return multimeter measurement as IEEE 754 floating point value; this\n  value is scaled to the appropriate base unit for the mode in which the\n  multimeter is currently operating..\n* `0x02`: Return multimeter display as IEEE 754 floating point value.\n  Note that this value is not scaled to handle displayed SI magnitudes!\n* `0x10`: Return current display flags as bits in this order:\n  * 31:\n  * 30: Sign\n  * 29: Low Battery\n  * 28: Hold\n  * 27: Rel\n  * 26: Beep\n  * 25: Sign (?)\n  * **24**: RS232\n  * 23: AUTO\n  * 22: \n  * 21: \n  * 20: M (mega)\n  * 19: k (kilo)\n  * 18: m (milli)\n  * 17: n (nano)\n  * **16**: µ (micro)\n  * 15: C2C1 00 (?)\n  * 14: C2C1 01 (?)\n  * 13: C2C1 10 (?)\n  * 12: C2C1 11 (?)\n  * 11:\n  * 10: Diode\n  * 09: DC\n  * **08**: AC\n  * 07:\n  * 06:\n  * 05: %\n  * 04: Hz\n  * 03: V\n  * 02: A\n  * 01: F\n  * 00: Ω\n\n#### SPI Troubleshooting\n\nThe device itself operates as an SPI slave, and it's rather difficult to\nkeep up with fast SPI speeds with just a 12Mhz clock, so if you have unreliable\nresults, try slowing down your SPI bus speed -- it's not like you're\ngoing to ever be able to get more than a few measurements/second\nanyway given that the multimeter itself only measures 2-3x second.\n\n#### Arduino Example\n\n```c\n#include \u003cSPI.h\u003e\n\n#define MM_PIN 9\n\nvoid setup() {\n  digitalWrite(MM_PIN, HIGH);\n  pinMode(MM_PIN, OUTPUT);\n  pinMode(MISO, INPUT);\n  pinMode(MOSI, OUTPUT);\n  pinMode(SCK, OUTPUT);\n  SPI.begin();\n  SPI.beginTransaction(SPISettings(1000, MSBFIRST, SPI_MODE0));\n\n  Serial.begin(9600);\n}\n\nvoid loop() {\n  union {\n      float measurement;\n      unsigned char bytes[4];\n  } floatMeasurement;\n\n  digitalWrite(MM_PIN, LOW);\n\n  // Let's get the current measurement\n  SPI.transfer(0x01);\n  for(uint8_t i = 0; i \u003c 4; i++) {\n    floatMeasurement.bytes[i] = SPI.transfer(i);\n  }\n  Serial.println(floatMeasurement.measurement, 7);\n  digitalWrite(MM_PIN, HIGH);\n\n  delay(500);\n\n  // Now let's print the current flags\n  digitalWrite(MM_PIN, LOW);\n  SPI.transfer(0x10);\n  for(uint8_t i = 0; i \u003c 4; i++) {\n    Serial.println(SPI.transfer(i), BIN);\n  }\n  digitalWrite(MM_PIN, HIGH);\n\n  delay(3000);\n}\n```\n\n## Hardware\n\n![](https://s3-us-west-2.amazonaws.com/coddingtonbear-public/github/bullion/bullion.svg)\n\nCheck out the `hardware` directory to find Kicad schematics and layout.  The\nlayout you'll find was designed for *homemade* *pcb* *fabrication* (note how \nbig the vias are and the presence of \"transit\" vias for working around the\nlack of through-hole plating), but it could be sent to your favorite PCB\nboardhouse for manufacture if desired.\n\nThe following major components are used (see the schematic for details):\n\n* ATMEGA328PB Microcontroller in the QFP package. A normal ATMEGA328P\n  would work fine, too, but you will have to update a handful of SPI-related\n  register and interrupt names to remove the extra zero (the -PB version\n  has two SPI peripherals).\n  Although the ATMEGA328PB is a little more capable than the ATMEGA328P\n  these days, they are just a little cheaper; both are around 2.5 USD.\n* CH340G USB-to-UART IC: You can buy these from Aliexpress or wherever\n  for less than 0.50 USD.\n* 12Mhz Crystal (SMD HC-49)\n* A MicroUSB connector.\n* A standard through-hole 3.5mm stereo connector.\n\nNote that the design relies upon the CH340G chip sharing the\nmicrocontroller's clock; you will want to set the `CKOUT=0` fuse\n(generally titled \"Clock output on PORTB0\").\n\n## Future Thoughts\n\nThere are lots of things about this project that I'd change if I were to\napproach it again; those include:\n\n* Making the primary serial interface I2C instead of SPI.\n    * I2C provides a lot more flexibility for letting a device take\n      extra time to perform slow operations via \"clock stretching\".  As\n      this is currently designed, SPI is used, and the client device must\n      be able to keep up with the clock speed set by the master or data\n      will be lost.\n    * With I2C, you can save a wire or two!\n    * The downside is that we might have to expose a couple extra pins\n      since the current header is used for both programming and the serial\n      interface.  If I2C is added, either two additional header pins will\n      need to be added, or maybe a multiplexer chip allowing two header\n      pins to be shared individually between two different microcontroller\n      pins.\n* Orient the microcontroller at a 45˚ angle.  This should make routing a\n  little less chaotic.\n* Add reverse current protection!  Not having such protection was a little\n  bit of an embarassing oversight.\n* Use either a MicroUSB breakout board or a MiniUSB connector instead of\n  the existing MicroUSB connector. Soldering that tiny connector onto\n  a homemade PCB is very difficult -- the pin pitch of those connectors\n  is 0.65mm; just a smidge below what my current process is able to\n  resolve (~0.75mm) without needing to use a sharp knife to separate\n  traces.\n* Perhaps place devices on both sides of the board to save space?  It's\n  not clear to me whether that would be worth it, but it could make the\n  board a lot smaller.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoddingtonbear%2Fbullion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoddingtonbear%2Fbullion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoddingtonbear%2Fbullion/lists"}