{"id":3443,"date":"2024-06-11T14:16:29","date_gmt":"2024-06-11T18:16:29","guid":{"rendered":"https:\/\/www.yorku.ca\/professor\/drsmith\/?p=3443"},"modified":"2024-06-11T15:46:38","modified_gmt":"2024-06-11T19:46:38","slug":"more-firmata4j-and-sensors","status":"publish","type":"post","link":"https:\/\/www.yorku.ca\/professor\/drsmith\/2024\/06\/11\/more-firmata4j-and-sensors\/","title":{"rendered":"Firmata4j and a Simple DHT20 example"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"alignright size-large is-resized\"><img decoding=\"async\" src=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-3.44.49\u202fPM-1024x605.png\" alt=\"DHT20 sensor\" class=\"wp-image-3454\" width=\"200\" srcset=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-3.44.49\u202fPM-1024x605.png 1024w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-3.44.49\u202fPM-300x177.png 300w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-3.44.49\u202fPM-1536x908.png 1536w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-3.44.49\u202fPM-2048x1211.png 2048w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-3.44.49\u202fPM-768x454.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>DHT20 sensor on the Grove Beginner Kit for Arduino board.<\/figcaption><\/figure><\/div>\n\n\n\n<p>After my <a href=\"https:\/\/www.yorku.ca\/professor\/drsmith\/2024\/06\/11\/firmata-example-i2c-sensor-java-firmata4j\/\">earlier blog post<\/a> from today, I wanted to verify that I could read single bytes of data from other sensors on the Grove Beginner Kit for Arduino.  The next target?  The DHT20 sensor.  According to the <a href=\"https:\/\/files.seeedstudio.com\/products\/101020932\/DHT20-Product-Manual.pdf\">data sheet<\/a>, I should be able to be able to request a status byte and that that value should typically be 0x18.  <\/p>\n\n\n\n<p>So I modified the code from the previous post.  <\/p>\n\n\n\n<p>Here is the communication on the I2C bus.  You can see the command to the DHT20 sensor on the left and then its response on the right.  The purple is the UART signal back to the PC.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"235\" src=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-2.04.02\u202fPM-1024x235.png\" alt=\"\" class=\"wp-image-3445\" srcset=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-2.04.02\u202fPM-1024x235.png 1024w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-2.04.02\u202fPM-300x69.png 300w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-2.04.02\u202fPM-1536x352.png 1536w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-2.04.02\u202fPM-2048x470.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>I2C command and response for the DHT20 sensor, generated and interpreted by Firmata4j.<\/figcaption><\/figure>\n\n\n\n<p>And we can see, in IntelliJ, from the console, that the data comes back as expected: 0x18:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"324\" src=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-2.13.29\u202fPM-1024x324.png\" alt=\"\" class=\"wp-image-3446\" srcset=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-2.13.29\u202fPM-1024x324.png 1024w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-2.13.29\u202fPM-300x95.png 300w, https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2024\/06\/Screenshot-2024-06-11-at-2.13.29\u202fPM.png 1039w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>IntelliJ console showing data back from the sensor. (0x18)<\/figcaption><\/figure>\n\n\n\n<p>The changes to the previous code?  First in main, then replacing the BMP280 files with equivalents for the DHT20.<\/p>\n\n\n\n<p>MainClass.java<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nimport org.firmata4j.I2CDevice;\nimport org.firmata4j.firmata.FirmataDevice;\n\nimport java.io.IOException;\n\npublic class MainClass {\n\n    static String USBPORT = \"\/dev\/cu.usbserial-0001\"; \/\/ TO-DO : modify based on your computer setup.\n\n    public static void main(String&#91;] args) throws IOException, InterruptedException {\n        var myUSBPort = USBPORT;\n\n        var groveArduinoBoard = new FirmataDevice(myUSBPort);\n        groveArduinoBoard.start();\n        groveArduinoBoard.ensureInitializationIsDone();\n\n        \/\/ Set up the DHT20 sensor &amp; a listener for I2C events.\n        I2CDevice firmataToI2CPressureSensor =\n                groveArduinoBoard.getI2CDevice(Dht20Token.DHT20_ADDR);                        \/\/ Sensor as I2C Object.\n        SensorI2CListener  myI2CListener  = new SensorI2CListener(firmataToI2CPressureSensor);  \/\/ Listener setup.\n        firmataToI2CPressureSensor.subscribe(myI2CListener);                                    \/\/ Subscribe to listener\n        Dht20 groveDht20Sensor = new Dht20(firmataToI2CPressureSensor, myI2CListener);       \/\/ DHT20 specifics\n\n        \/\/ Initialize the sensor.  Ask it for its ID.\n        groveDht20Sensor.init();  \/\/ init() method is like the SSD1306 Method.\n\n        \/\/ Shut off connection to the board.\n        groveArduinoBoard.stop();\n    }\n}\n\n<\/code><\/pre>\n\n\n\n<p>Dht20.java<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* model this after the SSD1306 class by Oleg Kurbatov *\/\n\nimport org.firmata4j.I2CDevice;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.IOException;\nimport java.util.Arrays;\n\nimport static java.lang.Integer.toHexString;\n\npublic class Dht20 {\n    private final I2CDevice theDHTdevice;\n    private final SensorI2CListener myI2CListener;\n    private static final Logger LOGGER = LoggerFactory.getLogger(Dht20.class);\n\n    \/* constructor 1 *\/\n    public Dht20(I2CDevice theBMPdevice, SensorI2CListener myI2CListener) {\n        this.theDHTdevice = theBMPdevice;\n        this.myI2CListener = myI2CListener;\n    }\n\n    \/* Initialize the Bmp280 sensor by asking for its ID. *\/\n    public void init() throws InterruptedException {\n\n\n        \/\/ 1. Tell the chip.\n        try{\n            theDHTdevice.tell(Dht20Token.DHT20_STATUS_ASK);\n            System.out.println(\"I2C telling...\");\n        }        catch (IOException e){\n            throw new RuntimeException(e);\n        }\n\n        \/\/ 2. Pause briefly.\n        Thread.sleep(1);\n\n        \/\/ 3. listen.  (ask)\n        try {\n            theDHTdevice.ask((byte)1, myI2CListener);\n            System.out.println(\"I2C asking...\");\n\n        } catch (IOException e) {\n            throw new RuntimeException(e);\n        }\n\n        Thread.sleep(20);\n        System.out.println(\"The DHT20 address: (after asking...): 0x\" + toHexString(theDHTdevice.getAddress()));\n\n    }\n\n\n    \/* basic I2C command method.\n     *  Copied from SSD1306.java *\/\n    private void command (byte... commandBytes){\n        try{\n            for(int i = 0; i &lt; commandBytes.length; i += 2){\n                theDHTdevice.tell(Arrays.copyOfRange(commandBytes,i,i+2));\n            }\n        }\n        catch (IOException e){\n            throw new RuntimeException(e);\n        }\n    }\n}\n\n<\/code><\/pre>\n\n\n\n<p>Dht20Token.java<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\/* DHT20 constants for I2C communicition.\n *\n * Based on approach taken by Oleg Kurbatov and the SSD1306Token interface file.\n *\/\npublic interface Dht20Token {\n     final byte DHT20_ADDR = (byte) 0x38;\n     final byte DHT20_STATUS_ASK = (byte) 0x71;\n\n }<\/code><\/pre>\n\n\n\n<p>SensorI2CListen.java<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import org.firmata4j.I2CDevice;\nimport org.firmata4j.I2CEvent;\nimport org.firmata4j.I2CListener;\n\nimport java.math.BigInteger;\nimport java.util.Arrays;\n\npublic class SensorI2CListener implements I2CListener{\n\n    private final I2CDevice theI2CDevice;\n    SensorI2CListener(I2CDevice theI2CDevice){\n        this.theI2CDevice = theI2CDevice;\n    }\n    @Override\n    public void onReceive(I2CEvent theI2CEvent) {\n\n        \/\/ Print out the event details (address, data, etc.)\n        System.out.println(\"Listener reports the following information: \");\n        System.out.println(\"The event:\" + theI2CEvent + \". Note: data is in base 10.\");\n        System.out.println(\"the Device address: \" +theI2CEvent.getDevice());\n        System.out.println(\"Event data array: \" + Arrays.toString(theI2CEvent.getData()) + \" in base 10.\");\n        \/* convert the byte array and print it *\/\n        String hexString = new BigInteger(1,theI2CEvent.getData()).toString(16);\n        System.out.println(\"Event data array: 0x\" + hexString);\n        \/* again, but compact *\/\n        System.out.println(\"Event data array: 0x\" + new BigInteger(1,theI2CEvent.getData()).toString(16));\n\n\n    }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Dependencies<\/h2>\n\n\n\n<p>This code is dependant on the Firmata4j library which, in turn, requires JSSC, jSerialComm and SLF4J.  All of these are packaged into a <a href=\"https:\/\/github.com\/onnimikki\/Firmata4j_JAR\/blob\/main\/Firmata2pt3pt9_June2024.jar\">single JAR file located on GitHub<\/a>.  The JAR is based on the <a href=\"https:\/\/github.com\/kurbatov\/firmata4j\/tree\/master\">2.3.9 release of Firmata4j<\/a>, which is available on GitHub but not on Maven.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>It works.  But it needs further development to capture more useful data.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"128\" height=\"128\" src=\"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-content\/uploads\/sites\/444\/2021\/12\/noun-signature-1720818-2.png\" alt=\"a pen\" class=\"wp-image-2116\"\/><\/figure><\/div>\n\n\n\n<p>James Andrew Smith is a Professional Engineer and Associate Professor in the Electrical Engineering and Computer Science\u00a0<a href=\"http:\/\/eecs.lassonde.yorku.ca\">Department<\/a>\u00a0of York University's\u00a0<a href=\"http:\/\/lassonde.yorku.ca\">Lassonde School<\/a>, with degrees in Electrical and Mechanical Engineering\u00a0from the University of Alberta and McGill University.\u00a0\u00a0Previously a program director in biomedical engineering, his research background spans robotics, locomotion, human birth and\u00a0engineering\u00a0education. While on sabbatical in 2018-19 with his wife and kids he lived in Strasbourg, France and\u00a0he\u00a0taught at the\u00a0<a href=\"https:\/\/www.insa-strasbourg.fr\/en\/\">INSA Strasbourg<\/a>\u00a0and\u00a0<a href=\"https:\/\/www.hs-karlsruhe.de\">Hochschule Karlsruhe<\/a>\u00a0and wrote about his\u00a0<a href=\"https:\/\/twitter.com\/search?q=(%23sabbaticallife)%20(from%3Aonnimikki)&amp;src=typed_query\">personal<\/a>\u00a0and\u00a0<a href=\"https:\/\/twitter.com\/search?q=insa%20(from%3Ajasmith_yorku)&amp;src=typed_query\">professional\u00a0<\/a><a href=\"https:\/\/twitter.com\/search?q=karlsruhe%20(from%3Ajasmith_yorku)&amp;src=typed_query\">perspectives<\/a>.\u00a0\u00a0James is a proponent of using social media to advocate for justice, equity, diversity and inclusion as well as evidence-based applications of research\u00a0in the public sphere.\u00a0You can find him on\u00a0<a href=\"https:\/\/twitter.com\/jasmith_yorku\">Twitter<\/a>. Originally from Qu\u00e9bec City, he now lives in Toronto, Canada.\u00a0\u00a0<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After my earlier blog post from today, I wanted to verify that I could read single bytes of data from other sensors on the Grove Beginner Kit for Arduino. The next target? The DHT20 sensor. According to the data sheet, I should be able to be able to request a status byte and that that [&hellip;]<\/p>\n","protected":false},"author":762,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","footnotes":""},"categories":[42,687,50],"tags":[690,610,20,691,689,227,692],"class_list":["post-3443","post","type-post","status-publish","format-standard","hentry","category-arduino","category-firmata","category-java","tag-dht20","tag-firmata4j","tag-grove-beginner-kit-for-arduino","tag-humidity-sensor","tag-i2c","tag-sensors","tag-temperature-sensor"],"taxonomy_info":{"category":[{"value":42,"label":"arduino"},{"value":687,"label":"FIrmata"},{"value":50,"label":"java"}],"post_tag":[{"value":690,"label":"DHT20"},{"value":610,"label":"firmata4j"},{"value":20,"label":"grove beginner kit for arduino"},{"value":691,"label":"humidity sensor"},{"value":689,"label":"I2C"},{"value":227,"label":"sensors"},{"value":692,"label":"temperature sensor"}]},"featured_image_src_large":false,"author_info":{"display_name":"drsmith","author_link":"https:\/\/www.yorku.ca\/professor\/drsmith\/author\/drsmith\/"},"comment_info":"","category_info":[{"term_id":42,"name":"arduino","slug":"arduino","term_group":0,"term_taxonomy_id":42,"taxonomy":"category","description":"","parent":0,"count":30,"filter":"raw","cat_ID":42,"category_count":30,"category_description":"","cat_name":"arduino","category_nicename":"arduino","category_parent":0},{"term_id":687,"name":"FIrmata","slug":"firmata","term_group":0,"term_taxonomy_id":687,"taxonomy":"category","description":"","parent":0,"count":7,"filter":"raw","cat_ID":687,"category_count":7,"category_description":"","cat_name":"FIrmata","category_nicename":"firmata","category_parent":0},{"term_id":50,"name":"java","slug":"java","term_group":0,"term_taxonomy_id":50,"taxonomy":"category","description":"","parent":0,"count":27,"filter":"raw","cat_ID":50,"category_count":27,"category_description":"","cat_name":"java","category_nicename":"java","category_parent":0}],"tag_info":[{"term_id":690,"name":"DHT20","slug":"dht20","term_group":0,"term_taxonomy_id":690,"taxonomy":"post_tag","description":"","parent":0,"count":1,"filter":"raw"},{"term_id":610,"name":"firmata4j","slug":"firmata4j","term_group":0,"term_taxonomy_id":610,"taxonomy":"post_tag","description":"","parent":0,"count":5,"filter":"raw"},{"term_id":20,"name":"grove beginner kit for arduino","slug":"grove-beginner-kit-for-arduino","term_group":0,"term_taxonomy_id":20,"taxonomy":"post_tag","description":"","parent":0,"count":4,"filter":"raw"},{"term_id":691,"name":"humidity sensor","slug":"humidity-sensor","term_group":0,"term_taxonomy_id":691,"taxonomy":"post_tag","description":"","parent":0,"count":1,"filter":"raw"},{"term_id":689,"name":"I2C","slug":"i2c","term_group":0,"term_taxonomy_id":689,"taxonomy":"post_tag","description":"","parent":0,"count":2,"filter":"raw"},{"term_id":227,"name":"sensors","slug":"sensors","term_group":0,"term_taxonomy_id":227,"taxonomy":"post_tag","description":"","parent":0,"count":3,"filter":"raw"},{"term_id":692,"name":"temperature sensor","slug":"temperature-sensor","term_group":0,"term_taxonomy_id":692,"taxonomy":"post_tag","description":"","parent":0,"count":1,"filter":"raw"}],"_links":{"self":[{"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/posts\/3443","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/users\/762"}],"replies":[{"embeddable":true,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/comments?post=3443"}],"version-history":[{"count":6,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/posts\/3443\/revisions"}],"predecessor-version":[{"id":3455,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/posts\/3443\/revisions\/3455"}],"wp:attachment":[{"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/media?parent=3443"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/categories?post=3443"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.yorku.ca\/professor\/drsmith\/wp-json\/wp\/v2\/tags?post=3443"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}