{"id":9115,"date":"2026-01-28T19:03:23","date_gmt":"2026-01-29T03:03:23","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=9115"},"modified":"2026-01-29T19:40:50","modified_gmt":"2026-01-30T03:40:50","slug":"using-ai-edits-to-add-new-functionality-to-projects","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/ai\/thermostat\/02-newlogic\/","title":{"rendered":"Using AI Edits to Add New Functionality to Projects"},"content":{"rendered":"<p>This tutorial continues the series where we are using AI to turn a third-party <a href=\"https:\/\/gitlab.com\/slimhazard\/picow-http-example\">open-source HTTP server for Raspberry Pi Pico<\/a> into a smart thermostat. In the <a href=\"https:\/\/visualgdb.com\/tutorials\/ai\/thermostat\/01-refactoring\">previous tutorial<\/a> we refactored the ADC and LED-related logic from the existing project into a separate Thermostat module. In this tutorial we will extend the thermostat module to actually control the output based on the temperature.<\/p>\n<p>Before you begin this tutorial, follow the previous one, or check out the <strong>02-adding-logic<\/strong> tag from the <a href=\"https:\/\/gitlab.com\/sysprogs-tutorials\/picow-http-example\">tutorial repository<\/a>. Once the ADC and LED code has been moved to the Thermostat module, proceed with the steps below to start adding the actual thermostat functionality.<\/p>\n<ol>\n<li>First of all, we will create a new FreeRTOS task for the thermostat. You can search for <strong>xTaskCreate<\/strong> to find that the other tasks are created in <strong>main():<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-task.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9116\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-task.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-task.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-task-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-task-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-task-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/strong><\/li>\n<li>If we wanted to add another task manually, we would need to copy one of the <strong>xTaskCreate()<\/strong> calls, create a separate variable for the new task, and create declaration + implementation for the task body. With AI, you can do it by clicking on the edit button and using this prompt:x\n<pre>+ThermostatTask in @ThermostatController.c (empty for now)<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-prompt.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9117\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-prompt.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-prompt.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-prompt-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-prompt-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-prompt-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a>Note how typing @ in the prompt box opens the suggestion popup showing all symbols and files visible from the current file.<\/li>\n<li>Most models will handle it just fine:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-created.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9118\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-created.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-created.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-created-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-created-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-created-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<li>We can ask the model to pass &amp;g_Thermostat as the parameter to the task body by using this prompt:\n<pre>&amp;g_Thermostat as arg<\/pre>\n<p>VisualGDB automatically passes the definition of xTaskCreate() to the language model, so it will know which function argument gets passed to the body, and will also add casting code inside the body:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-v2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9119\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-v2.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-v2.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-v2-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-v2-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-v2-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<li>Now we will implement the actual thermostat control loop. It&#8217;s a very straight-forward algorithm: the heater should be turned on if the temperature drops below the low threshold, and it should stay on until the temperature is above the high threshold. Doing it manually would involve adding fields for temperature &amp; tolerance, setter functions if we wanted to keep things modular, and implementing the actual loop. AI can do it with a prompt like this:\n<pre>Implement thermostat loop with @Thermostat_GetTemperatureK and @Thermostat_SetOutputValue . Add TargetTemperature\/Tolerance fields &amp; setter funcs.<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-loop.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9120\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-loop.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-loop.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-loop-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-loop-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-loop-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a>Smaller models can do it just fine in a couple of seconds, which is way faster than doing it by hand.<\/li>\n<li>Note that the model decided to set the default values right in the task, that could cause a race condition if some other code sets them earlier. You can move initialization to the init function with this prompt:\n<pre>set defaults in @Thermostat_Init<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-move.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9121\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-move.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-move.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-move-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-move-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-move-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<li>To maximize the editing performance, VisualGDB heavily trims the code going into the language model. If you are editing <strong>ThermostatTask()<\/strong>, it will normally only see the function itself, the <strong>ThermostatController<\/strong> struct that is used inside it, and the <strong>GetTemperature()\/SetOutput() <\/strong>functions that were explicitly mentioned in the prompt (along with their dependencies). This allows doing most edits in a few seconds, but limits the AI&#8217;s capability of automatically finding relevant code. You can tweak this behavior by using the scope controls:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-scope-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9123\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-scope-1.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-scope-1.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-scope-1-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-scope-1-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-scope-1-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a>Any symbol in any source file can be added to the context window as read-only (declaration only) or editable (declaration + body), and you can control the depth of reference discovery. E.g. if <strong>ThermostatTask()<\/strong> refers to <strong>struct Thermostat<\/strong>, and <strong>struct Thermostat<\/strong> refers to <strong>critical_section_t<\/strong>, this is considered 2 levels of depth. You can change the reference depth in the primary scope popup, and preview the prompt size in the prompt window.<\/li>\n<li>If you try building and running the project now, it will crash as soon as ThermostatTask() tries setting the output. This happens because the cyw43 driver has not been initialized yet:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-crash.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9124\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-crash.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-crash.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-crash-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-crash-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-crash-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<li>To fix it, let&#8217;s update the thermostat task to wait until someone sets the <strong>IsRunning<\/strong> field to true:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-add2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9125\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-add2.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-add2.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-add2-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-add2-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-add2-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<li>We could create the new field and the function setting it by hand, but AI can do it faster. Use the &#8220;Add IsRunning &amp; Start function&#8221; prompt:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-added.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9126\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-added.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-added.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-added-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-added-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-added-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a>Note how AI decided to take the critical section in <strong>Thermostat_Start()<\/strong>, although it&#8217;s not required in this case. In this case it is easier to fix this by hand, but you could also refine it with a short prompt (e.g. &#8220;no critsec&#8221;).<\/li>\n<li>Finally, call <strong>Thermostat_Start()<\/strong> from <strong>initiate_http()<\/strong> after the call to <strong>cygw43_arch_init() <\/strong>to actually start the thermostat:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/12-call.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9127\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/12-call.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/12-call.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/12-call-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/12-call-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/12-call-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<li>Update the <a href=\"https:\/\/gitlab.com\/sysprogs-tutorials\/picow-http-example\/-\/blob\/9665092d6364185d79fca1bcb23206c11c6ff90f\/www\/index.html\"><strong>www\/index.html<\/strong><\/a> and <a href=\"https:\/\/gitlab.com\/sysprogs-tutorials\/picow-http-example\/-\/blob\/9665092d6364185d79fca1bcb23206c11c6ff90f\/www\/sample_app.js\"><strong>www\/sample_app.js<\/strong><\/a> files to match <a href=\"https:\/\/gitlab.com\/sysprogs-tutorials\/picow-http-example\/-\/commit\/9665092d6364185d79fca1bcb23206c11c6ff90f\">this commit<\/a> and press F5 to start debugging the project. The Raspberry Pi Pico board should connect to the Wi-Fi, and opening it in the browser should show this page:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/13-page.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9128\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/13-page.png\" alt=\"\" width=\"674\" height=\"370\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/13-page.png 674w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/13-page-300x165.png 300w\" sizes=\"(max-width: 674px) 100vw, 674px\" \/><\/a>If you have difficulties running or debugging the project, you can force the single-core mode by adding <strong>configNUMBER_OF_CORES=1<\/strong> to <strong>target_compile_definitions(PicoThermostat).<\/strong><\/li>\n<\/ol>\n<p>Note that the target and current temperature fields won&#8217;t work yet because we have not added handlers for the <strong>\/api\/getconfig<\/strong> and <strong>\/api\/settemp<\/strong> calls used by the JavaScript file. Follow the <a href=\"https:\/\/visualgdb.com\/tutorials\/ai\/thermostat\/03-adding-similar-code\/\">next tutorial<\/a> for detailed instructions on adding them.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial continues the series where we are using AI to turn a third-party open-source HTTP server for Raspberry Pi<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[253],"tags":[254,133,231],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/9115"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=9115"}],"version-history":[{"count":3,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/9115\/revisions"}],"predecessor-version":[{"id":9163,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/9115\/revisions\/9163"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=9115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=9115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=9115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}