{"id":17510,"date":"2024-02-19T11:07:28","date_gmt":"2024-02-19T16:07:28","guid":{"rendered":"https:\/\/scruss.com\/blog\/?p=17510"},"modified":"2024-02-19T11:07:54","modified_gmt":"2024-02-19T16:07:54","slug":"crickets-in-february","status":"publish","type":"post","link":"https:\/\/scruss.com\/blog\/2024\/02\/19\/crickets-in-february\/","title":{"rendered":"Crickets in February"},"content":{"rendered":"\n<p>It&#8217;s mid-February in Toronto: -10 \u00b0C and snowy. The memory of chirping summer fields is dim. But in my heart there is always <a href=\"https:\/\/scruss.com\/blog\/2004\/09\/22\/reminder-of-summer-field-recording\/\">a cricket-loud meadow<\/a>.<\/p>\n\n\n\n<p>Short of moving somewhere warmer, I&#8217;m going to have to make my own midwinter crickets. I have micro-controllers and tiny speakers: how hard can this be?<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"640\" style=\"aspect-ratio: 360 \/ 640;\" width=\"360\" controls loop src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2024\/02\/crickets1.webm\"><\/video><figcaption class=\"wp-element-caption\">more fun than a bucket of simulated crickets<br>(video description: a plastic box containing three USB power banks, each with USB cable leading to a Raspberry Pi Pico board. Each board has a small electromagnetic speaker attached between ground and a data pin)<\/figcaption><\/figure>\n\n\n\n<p>I could have merely made these beep away at a fixed rate, but I know that real crickets tend to chirp faster as the day grows warmer. This relationship is frequently referred to as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Dolbear%27s_law\">Dolbear&#8217;s law<\/a>. The American inventor <a href=\"https:\/\/en.wikipedia.org\/wiki\/Amos_Dolbear\">Amos Dolbear<\/a> published his observation (without data or species identification) in <em>The American Naturalist<\/em> in 1897: <a href=\"https:\/\/www.jstor.org\/stable\/2453256\">The Cricket as a Thermometer<\/a> \u2014<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"973\" height=\"555\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2024\/02\/Screenshot-from-2024-02-19-08-33-18.png\" alt=\"journal text:\n\nThe rate of chirp seems to be entirely determined by the temperature and this to such a degree that one may easily compute the temperature when the number of chirps per minute is known.\n\nThus at 60\u00b0 F. the rate is 80 per minute.\n\nAt 70\u00b0 F. the rate is 120 a minute, a change of four chirps a minute for each change of one degree. Below a temperature\nof 50\u00b0 the cricket has no energy to waste in music and there would be but 40 chirps per minute.\nOne may express this relation between temperature and chirp rate thus.\nLet T. stand for temperature and N,  the rate per minute.\n\n(typeset equation)\nT. = 50 + (N - 40) \/ 4\" class=\"wp-image-17512\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2024\/02\/Screenshot-from-2024-02-19-08-33-18.png 973w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2024\/02\/Screenshot-from-2024-02-19-08-33-18-320x183.png 320w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2024\/02\/Screenshot-from-2024-02-19-08-33-18-160x91.png 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2024\/02\/Screenshot-from-2024-02-19-08-33-18-768x438.png 768w\" sizes=\"auto, (max-width: 973px) 100vw, 973px\" \/><figcaption class=\"wp-element-caption\">pretty bold assertions there without data eh, Amos old son \u2026?<\/figcaption><\/figure>\n\n\n\n<p>When emulating crickets I&#8217;m less interested in the rate of chirps per minute, but rather in the period between chirps. I could also care entirely less about barbarian units, so I reformulated it in \u00b0C (<em>t<\/em>) and milliseconds (<em>p<\/em>):<\/p>\n\n\n\n<p class=\"has-text-align-center\"><em>t = \u2151 \u00d7 (40 + 75000 \u00f7 p)<\/em><\/p>\n\n\n\n<p>Since I know that the micro-controller has an internal temperature sensor, I&#8217;m particularly interested in the inverse relationship:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><em>p = 15000 <em>\u00f7<\/em> (9 * t \u00f7 5 &#8211; 8)<\/em><\/p>\n\n\n\n<p>I can check this against one of Dolbear&#8217;s observations for 70\u00b0F (= 21\u2151 \u00b0C, or 190\/9) and 120 chirps \/ minute (= 2 Hz, or a period of 500 ms):<\/p>\n\n\n\n<p><em>p = 15000 <em>\u00f7<\/em> (9 * t \u00f7 5 &#8211; 8)<\/em><br><em>\u00a0\u00a0\u00a0= 15000 <em>\u00f7<\/em> (9 * (190 \u00f7 9) \u00f7 5 &#8211; 8)<\/em><br><em>\u00a0\u00a0\u00a0= 15000 <em>\u00f7<\/em> (190 \u00f7 5 &#8211; 8)<\/em><br><em>\u00a0\u00a0\u00a0= 15000 <em>\u00f7<\/em> 30<\/em><br><em>\u00a0\u00a0\u00a0= 500<\/em><\/p>\n\n\n\n<p>Now I&#8217;ve got the timing worked out, how about the chirp sound. From a couple of recordings of cricket meadows I&#8217;ve made over the years, I observed:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The total duration of a chirp is about \u215b s<\/li>\n\n\n\n<li>A chirp is made up of four distinct events:\n<ul class=\"wp-block-list\">\n<li>a quieter short tone;<\/li>\n\n\n\n<li>a longer louder tone of a fractionally higher pitch;<\/li>\n\n\n\n<li>the same longer louder tone repeated;<\/li>\n\n\n\n<li>the first short tone repeated<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>There is a very short silence between each tone<\/li>\n\n\n\n<li>Each cricket appears to chirp at roughly the same pitch: some slightly lower, some slightly higher<\/li>\n\n\n\n<li>The pitch of the tones is in the range 4500\u20135000 Hz: around D8 on the music scale<\/li>\n<\/ol>\n\n\n\n<p>I didn&#8217;t attempt to model the actual stridulating mechanism of a particular species of cricket. I made what sounded sort of right to me. Hey, if Amos Dolbear could make stuff up and get it accepted as a \u201claw\u201d, I can at least get away with pulse width modulation and tiny tinny speakers \u2026<\/p>\n\n\n\n<p>This is the profile I came up with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>21 ms of 4568 Hz at 25% duty cycle<\/li>\n\n\n\n<li>7 ms of silence<\/li>\n\n\n\n<li>28 ms of 4824 Hz at 50% duty cycle<\/li>\n\n\n\n<li>7 ms of silence<\/li>\n\n\n\n<li>28 ms of 4824 Hz at 50% duty cycle<\/li>\n\n\n\n<li>7 ms of silence<\/li>\n\n\n\n<li>21 ms of 4568 Hz at 25% duty cycle<\/li>\n\n\n\n<li>7 ms of silence<\/li>\n<\/ul>\n\n\n\n<p>That&#8217;s a total of 126 ms, or \u215b<em>ish<\/em> seconds. In the code I made each instance play at a randomly-selected relative pitch of \u00b1200 Hz on the above numbers.<\/p>\n\n\n\n<p>For the speaker, I have a bunch of cheap PC motherboard beepers. They have a Dupont header that spans four pins on a Raspberry Pi Pico header, so if you put one on the ground pin at pin 23, the output will be connected to pin 26, aka GPIO 20:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"680\" height=\"383\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2021\/02\/spkr.jpg\" alt=\"Raspberry Pi Pico with small piezo speaker connected to pins 23 (ground) and 26 (GPIO 20)\" class=\"wp-image-16636\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2021\/02\/spkr.jpg 680w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2021\/02\/spkr-320x180.jpg 320w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2021\/02\/spkr-160x90.jpg 160w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><figcaption class=\"wp-element-caption\">from a post where I did a very, <em>very<\/em> bad thing: <a href=\"https:\/\/scruss.com\/blog\/2021\/02\/24\/nyan-cat-except-it-gets-faster-rtttl-on-the-raspberry-pi-pico\/\">Nyan Cat, except it gets faster \u2014 RTTTL on the Raspberry Pi Pico<\/a><\/figcaption><\/figure>\n\n\n\n<p>So \u2014 <em>finally<\/em> \u2014 here&#8217;s the MicroPython code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n# cricket thermometer simulator - scruss, 2024-02\n# uses a buzzer on GPIO 20 to make cricket(ish) noises\n# MicroPython - for Raspberry Pi Pico\n# -*- coding: utf-8 -*-\n\nfrom machine import Pin, PWM, ADC, freq\nfrom time import sleep_ms, ticks_ms, ticks_diff\nfrom random import seed, randrange\n\nfreq(125000000)  # use default CPU freq\nseed()  # start with a truly random seed\npwm_out = PWM(Pin(20), freq=10, duty_u16=0)  # can&#039;t do freq=0\nled = Pin(&quot;LED&quot;, Pin.OUT)\nsensor_temp = machine.ADC(4)  # adc channel for internal temperature\nTOO_COLD = 10.0  # crickets don&#039;t chirp below 10 \u00b0C (allegedly)\ntemps = &#x5B;]  # for smoothing out temperature sensor noise\npersonal_freq_delta = randrange(400) - 199  # different pitch every time\nchirp_data = &#x5B;\n    # cadence, duty_u16, freq\n    # there is a cadence=1 silence after each of these\n    &#x5B;3, 16384, 4568 + personal_freq_delta],\n    &#x5B;4, 32768, 4824 + personal_freq_delta],\n    &#x5B;4, 32768, 4824 + personal_freq_delta],\n    &#x5B;3, 16384, 4568 + personal_freq_delta],\n]\ncadence_ms = 7  # length multiplier for playback\n\n\ndef chirp_period_ms(t_c):\n    # for a given temperature t_c (in \u00b0C), returns the\n    # estimated cricket chirp period in milliseconds.\n    #\n    # Based on\n    # Dolbear, Amos (1897). &quot;The cricket as a thermometer&quot;.\n    #   The American Naturalist. 31 (371): 970\u2013971. doi:10.1086\/276739\n    #\n    # The inverse function is:\n    #     t_c = (75000 \/ chirp_period_ms + 40) \/ 9\n    return int(15000 \/ (9 * t_c \/ 5 - 8))\n\n\ndef internal_temperature(temp_adc):\n    # see pico-micropython-examples \/ adc \/ temperature.py\n    return (\n        27\n        - ((temp_adc.read_u16() * (3.3 \/ (65535))) - 0.706) \/ 0.001721\n    )\n\n\ndef chirp(pwm_channel):\n    for peep in chirp_data:\n        pwm_channel.freq(peep&#x5B;2])\n        pwm_channel.duty_u16(peep&#x5B;1])\n        sleep_ms(cadence_ms * peep&#x5B;0])\n        # short silence\n        pwm_channel.duty_u16(0)\n        pwm_channel.freq(10)\n        sleep_ms(cadence_ms)\n\n\nled.value(0)  # led off at start; blinks if chirping\n### Start: pause a random amount (less than 2 s) before starting\nsleep_ms(randrange(2000))\n\nwhile True:\n    loop_start_ms = ticks_ms()\n    sleep_ms(5)  # tiny delay to stop the main loop from thrashing\n    temps.append(internal_temperature(sensor_temp))\n    if len(temps) &gt; 5:\n        temps = temps&#x5B;1:]\n    avg_temp = sum(temps) \/ len(temps)\n    if avg_temp &gt;= TOO_COLD:\n        led.value(1)\n        loop_period_ms = chirp_period_ms(avg_temp)\n        chirp(pwm_out)\n        led.value(0)\n        loop_elapsed_ms = ticks_diff(ticks_ms(), loop_start_ms)\n        sleep_ms(loop_period_ms - loop_elapsed_ms)\n<\/pre><\/div>\n\n\n<p>There are a few more details in the code that I haven&#8217;t covered here:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The program pauses for a short random time on starting. This is to ensure that if you power up a bunch of these at the same time, they don&#8217;t start exactly synchronized<\/li>\n\n\n\n<li>The Raspberry Pi Pico&#8217;s temperature sensor can be slightly noisy, so the chirping frequency is based on the average of (up to) the last five readings<\/li>\n\n\n\n<li>There&#8217;s no chirping below 10 \u00b0C, because Amos Dolbear said so<\/li>\n\n\n\n<li>The built-in LED also flashes if the board is chirping. It doesn&#8217;t mimic the speaker&#8217;s PWM cadence, though.<\/li>\n<\/ol>\n\n\n\n<p>Before I show you the next video, I need to say: <strong><em>no real crickets were harmed in the making of this post<\/em><\/strong>. I took the bucket outside (roughly -5 \u00b0C) and the \u201ccrickets\u201d stopped chirping as they cooled down. Don&#8217;t worry, they started back up chirping again when I took them inside.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"640\" style=\"aspect-ratio: 360 \/ 640;\" width=\"360\" controls src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2024\/02\/crickets2.webm\"><\/video><figcaption class=\"wp-element-caption\">\u201cIf You&#8217;re Cold They&#8217;re Cold, Bring Them Inside\u201d<br>(video description: a plastic box containing three USB power banks, each with USB cable leading to a Raspberry Pi Pico board. Each board has a small electromagnetic speaker attached between ground and a data pin)<\/figcaption><\/figure>\n\n\n\n<p><strong> <\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s mid-February in Toronto: -10 \u00b0C and snowy. The memory of chirping summer fields is dim. But in my heart there is always a cricket-loud meadow. Short of moving somewhere warmer, I&#8217;m going to have to make my own midwinter crickets. I have micro-controllers and tiny speakers: how hard can this be? I could have [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[3315],"tags":[1747,1422,2208,3332,24,3094,2510],"class_list":["post-17510","post","type-post","status-publish","format-standard","hentry","category-electronics","tag-annoying","tag-crickets","tag-electronics","tag-entomology","tag-futile","tag-micropython","tag-raspberrypi"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pQNZZ-4yq","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/17510","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/comments?post=17510"}],"version-history":[{"count":2,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/17510\/revisions"}],"predecessor-version":[{"id":17520,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/17510\/revisions\/17520"}],"wp:attachment":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/media?parent=17510"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/categories?post=17510"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/tags?post=17510"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}