{ "info": { "author": "Christian Fobel", "author_email": "christian@fobel.net", "bugtrack_url": null, "classifiers": [], "description": "# open-drop #\nControl package for OpenDrop Digital Microfluidics Platform\n\n## Overview ##\n\nThis package contains:\n\n - Firmware compatible with Arduino Uno or Mega2560.\n - Installable Python package for interfacing with Arduino firmware through\n serial port or i2c (through a serial-to-i2c proxy).\n\n## Install ##\n\nThe Python package can be installed through `pip` using the following command:\n\n pip install open-drop\n\n## Upload firmware ##\n\nTo upload the pre-compiled firmware included in the Python package, run the\nfollowing command:\n\n python -m open_drop.bin.upload \n\nreplacing `` with either `uno` or `mega2560`, depending on the\nmodel of the board.\n\nThis will attempt to upload the firmware by automatically discovering the\nserial port. On systems with multiple serial ports, use the `-p` command line\nargument to specify the serial port to use. For example:\n\n python -m open_drop.bin.upload -p COM3 uno\n\n--------------------------------------------------\n\n## Usage ##\n\nAfter uploading the firmware to the board, the `open_drop.Proxy` class can be\nused to interact with the Arduino device.\n\nSee the session log below for example usage.\n\n### Example interactive session ###\n\n >>> from serial import Serial\n >>> from open_drop import Proxy\n\nConnect to serial device.\n\n >>> serial_device = Serial('/dev/ttyUSB0', baudrate=115200)\n\nInitialize a device proxy using existing serial connection.\n\n >>> proxy = Proxy(serial_device)\n\nQuery the number of bytes free in device RAM.\n\n >>> proxy.ram_free()\n 409\n\nQuery descriptive properties of device.\n\n >>> proxy.properties()\n base_node_software_version 0.9.post8.dev141722557\n name open_drop\n manufacturer Wheeler Lab\n url http://github.com/wheeler-microfluidics/open-d...\n software_version 0.1\n dtype: object\n\nUse Arduino API methods interactively.\n\n >>> # Set pin 13 as output\n >>> proxy.pin_mode(13, 1)\n >>> # Turn led on\n >>> proxy.digital_write(13, 1)\n >>> # Turn led off\n >>> proxy.digital_write(13, 0)\n\nQuery number of available channels.\n\n >>> proxy.channel_count()\n 40\n\nQuery state of channels array.\n\n >>> proxy.state_of_channels\n array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=uint8)\n\nTurn on every other channel.\n\n >>> proxy.state_of_channels = 20 * [0, 1]\n\nQuery updated state of channels array.\n\n >>> proxy.state_of_channels\n array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,\n 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], dtype=uint8)\n\n### Configuration and state ###\n\nThe device stores a *configuration* and a *state*. The configuration is\nserialized and stored in EEPROM, allowing settings to persist across device\nresets. The state is stored in device memory and is reinitialized each time\nthe device starts up.\n\nPrint (non-default) configuration values.\n\n >>> print proxy.config\n serial_number: 2\n baud_rate: 115200\n i2c_address: 17\n\n >>> proxy.config.\n proxy.config.max_waveform_frequency proxy.config.max_waveform_voltage\n >>> proxy.config.max_waveform_voltage\n 200\n >>> proxy.config.max_waveform_frequency\n 10000\n\nSet voltage and frequency.\n\n >>> result_code = proxy.update_state(voltage=100, frequency=1e3)\n >>> print proxy.state\n voltage: 100.0\n frequency: 1000.0\n\n#### Validation ####\n\nNote that negative values are not allowed for voltage or frequency.\n\n >>> result_code = proxy.update_state(voltage=-1) # Negative voltage \n >>> print proxy.state\n voltage: 100.0\n frequency: 1000.0\n\nVoltage/frequency updates are restricted to allowable range.\n\n >>> result_code = proxy.update_state(voltage=300) # Voltage greater than max\n >>> print proxy.state # Voltage remains unchanged\n voltage: 100.0\n frequency: 1000.0\n\nMax values can be increased by updating the configuration.\n\n >>> result_code = proxy.update_config(max_waveform_voltage=300)\n >>> result_code = proxy.update_state(voltage=300) # Voltage now <= max\n >>> print proxy.state # Voltage changed\n voltage: 300.0\n frequency: 1000.0\n\nTo persist changes to configuration across device reset - *not* state - use\n`save_config` method.\n\n >>> proxy.save_config()\n\n### Other methods ###\n\nBelow is a list of the attributes of the `open_drop.Proxy` Python class. Note\nthat many of the [Arduino API][1] functions (e.g., `pin_mode`, `digital_write`,\netc.) are exposed through the RPC API.\n\n >>> proxy.\n proxy.analog_read proxy.microseconds\n proxy.analog_write proxy.milliseconds\n proxy.array_length proxy.name\n proxy.base_node_software_version proxy.on_config_baud_rate_changed\n proxy.begin proxy.on_config_i2c_address_changed\n proxy.buffer_size proxy.on_config_serial_number_changed\n proxy.channel_count proxy.on_state_frequency_changed\n proxy.config proxy.on_state_voltage_changed\n proxy.delay_ms proxy.pin_mode\n proxy.delay_us proxy.properties\n proxy.digital_read proxy.ram_free\n proxy.digital_write proxy.read_eeprom_block\n proxy.echo_array proxy.reset_config\n proxy.get_buffer proxy.reset_state\n proxy.i2c_address proxy.save_config\n proxy.i2c_available proxy.serialize_config\n proxy.i2c_buffer_size proxy.serialize_state\n proxy.i2c_read proxy.set_i2c_address\n proxy.i2c_read_byte proxy.set_state_of_channels\n proxy.i2c_request proxy.software_version\n proxy.i2c_request_from proxy.state\n proxy.i2c_scan proxy.state_of_channels\n proxy.i2c_write proxy.str_echo\n proxy.load_config proxy.update_config\n proxy.manufacturer proxy.update_eeprom_block\n proxy.max_i2c_payload_size proxy.update_state\n proxy.max_serial_payload_size proxy.url\n\n--------------------------------------------------\n\n## Firmware development ##\n\nThe Arduino firmware/sketch is located in the `open_drop/Arduino/open_drop`\ndirectory. The key functionality is defined in the `open_drop::Node` class in\nthe file `Node.h`.\n\nRunning the following command will build the firmware using [SCons][2] for\nArduino Uno and Arduino Mega2560, and will package the resulting firmware in a\nPython package, ready for distribution.\n\n paver sdist\n\n### Adding new remote procedure call (RPC) methods ###\n\nNew methods may be added to the RPC API by adding new methods to the\n`open_drop::Node` class in the file `Node.h`.\n\n# Author #\n\nCopyright 2015 Christian Fobel \n\n\n[1]: https://www.arduino.cc/en/Reference/HomePage\n[2]: http://www.scons.org/\n", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/wheeler-microfluidics/open-drop.git", "keywords": null, "license": "GPLv2", "maintainer": null, "maintainer_email": null, "name": "open-drop", "package_url": "https://pypi.org/project/open-drop/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/open-drop/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/wheeler-microfluidics/open-drop.git" }, "release_url": "https://pypi.org/project/open-drop/0.2.post21/", "requires_dist": null, "requires_python": null, "summary": "Arduino RPC node packaged as Python package.", "version": "0.2.post21" }, "last_serial": 1744712, "releases": { "0.2.post12": [ { "comment_text": "", "digests": { "md5": "e15152174e4fe58b9cc02aecae847f8c", "sha256": "5d7567d10a53f5ca338bc322170d6c631a5a2fb6ae9e0ccffe7a268f5bab1d02" }, "downloads": -1, "filename": "open-drop-0.2.post12.zip", "has_sig": false, "md5_digest": "e15152174e4fe58b9cc02aecae847f8c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 104671, "upload_time": "2015-09-15T19:08:44", "url": "https://files.pythonhosted.org/packages/59/ac/204174295efa40ce211995c5861bb5b51eb8af87632720b334955bd6b6e2/open-drop-0.2.post12.zip" } ], "0.2.post13": [ { "comment_text": "", "digests": { "md5": "c740809e1b6ca37bc85bce1a2c18f76c", "sha256": "1e3c249e14909172d82769a655943950c302bd17a53ed2e331dbd1c322b654a5" }, "downloads": -1, "filename": "open-drop-0.2.post13.zip", "has_sig": false, "md5_digest": "c740809e1b6ca37bc85bce1a2c18f76c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 104665, "upload_time": "2015-09-15T19:15:36", "url": "https://files.pythonhosted.org/packages/30/93/72f9e9456e6a43d9bae96c3f4d758e1b0a1d047de4a09f4f33c76f355a2a/open-drop-0.2.post13.zip" } ], "0.2.post14": [ { "comment_text": "", "digests": { "md5": "467f6c3efa27b23332b3a338859a3617", "sha256": "9c7e00636d818d0b206127d07fd50afd95e3b9419c134c7a8ed869ba9c63382c" }, "downloads": -1, "filename": "open-drop-0.2.post14.zip", "has_sig": false, "md5_digest": "467f6c3efa27b23332b3a338859a3617", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 104662, "upload_time": "2015-09-15T21:06:57", "url": "https://files.pythonhosted.org/packages/19/94/85533d2df57ab7de9393c1d8ec3488e4ac7a0cc252e496668010e9d8fc2d/open-drop-0.2.post14.zip" } ], "0.2.post15": [ { "comment_text": "", "digests": { "md5": "926cc5eff500dab8cf530a8c765853fc", "sha256": "f8b02189450a223e3454b89652f7e87310591e9e9474d391bc0000e2873bd657" }, "downloads": -1, "filename": "open-drop-0.2.post15.zip", "has_sig": false, "md5_digest": "926cc5eff500dab8cf530a8c765853fc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 104792, "upload_time": "2015-09-15T22:04:36", "url": "https://files.pythonhosted.org/packages/02/4a/9a30a52cd71fc39c1ad6c124c1708e3c1c235ae30dd8212a329094e26a4b/open-drop-0.2.post15.zip" } ], "0.2.post16": [ { "comment_text": "", "digests": { "md5": "2dc2dcf2ad49059f684fcd3f829fffde", "sha256": "527a0da4d562e86438269b0b7fd7a206aff4a1448c0743eedd7b8b69539cea5d" }, "downloads": -1, "filename": "open-drop-0.2.post16.zip", "has_sig": false, "md5_digest": "2dc2dcf2ad49059f684fcd3f829fffde", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 104857, "upload_time": "2015-09-15T22:29:24", "url": "https://files.pythonhosted.org/packages/2d/33/6dceef2c80d9d5fe2e179b539126206ba08b4f80042efd515ef1e4b4e353/open-drop-0.2.post16.zip" } ], "0.2.post17": [ { "comment_text": "", "digests": { "md5": "227509dc1fda08b06fda0f38594595ae", "sha256": "658b4136977f6fe112d9ed344a5ec66a09cf68923a5c5b68e6a4cf2741119635" }, "downloads": -1, "filename": "open-drop-0.2.post17.zip", "has_sig": false, "md5_digest": "227509dc1fda08b06fda0f38594595ae", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 143791, "upload_time": "2015-09-24T16:57:44", "url": "https://files.pythonhosted.org/packages/33/0f/4959cc173ed0d0d2f435871ab850deb3b577be307f3911e10971737f06e5/open-drop-0.2.post17.zip" } ], "0.2.post18": [ { "comment_text": "", "digests": { "md5": "76dd2b599a1777c5ec9ca880876cf38a", "sha256": "7b6c02fb35be50517fa883cbd6bafe1f5cbfbbc4980ed9beacc689ebd5d9ecd2" }, "downloads": -1, "filename": "open-drop-0.2.post18.zip", "has_sig": false, "md5_digest": "76dd2b599a1777c5ec9ca880876cf38a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 143794, "upload_time": "2015-09-25T18:44:49", "url": "https://files.pythonhosted.org/packages/bf/fa/ef3b89845ba8bce64a55546b8bde9ad4f94eb4a9dde03ea1f6028b5b20a2/open-drop-0.2.post18.zip" } ], "0.2.post19": [ { "comment_text": "", "digests": { "md5": "1c3553afa69c64248b407d12e862c162", "sha256": "21f6c3964f40b31bfffa6386ced0966f4afeb5834b84b4cc3d9d4953e11c6286" }, "downloads": -1, "filename": "open-drop-0.2.post19.zip", "has_sig": false, "md5_digest": "1c3553afa69c64248b407d12e862c162", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 104826, "upload_time": "2015-09-25T19:32:34", "url": "https://files.pythonhosted.org/packages/d0/74/92eac6ff29afc3885efaa053c4ccb51bf8a7d5a2aa5c5a7b3f8b4cc1c6bc/open-drop-0.2.post19.zip" } ], "0.2.post21": [ { "comment_text": "", "digests": { "md5": "926a8aa44d091ffd12abc69f27f0f99d", "sha256": "4235ba6f65c84dd32268b86bbf738044ad32bc3381a608c7564811b8a825f188" }, "downloads": -1, "filename": "open-drop-0.2.post21.zip", "has_sig": false, "md5_digest": "926a8aa44d091ffd12abc69f27f0f99d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 108714, "upload_time": "2015-09-29T22:03:12", "url": "https://files.pythonhosted.org/packages/73/9a/55cda48900c053613b44834ef66e476ca736dd7df5698ae126285f5fe05e/open-drop-0.2.post21.zip" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "926a8aa44d091ffd12abc69f27f0f99d", "sha256": "4235ba6f65c84dd32268b86bbf738044ad32bc3381a608c7564811b8a825f188" }, "downloads": -1, "filename": "open-drop-0.2.post21.zip", "has_sig": false, "md5_digest": "926a8aa44d091ffd12abc69f27f0f99d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 108714, "upload_time": "2015-09-29T22:03:12", "url": "https://files.pythonhosted.org/packages/73/9a/55cda48900c053613b44834ef66e476ca736dd7df5698ae126285f5fe05e/open-drop-0.2.post21.zip" } ] }