Pset 2: Embedded Programming

on circuits, microcontrollers, boards, and other things

Circuits

I have taken 8.02 Physics II, but I also have forgotten everything in it. I brush up on the ideas via Crash Course Physics on Youtube, specifically on electric charges, electric current, and circuit analysis. The short takeaway that I needed was that voltage is analogous to water pressure and current is analogous to its flow.

Much thanks to Anthony for his extensive explanations on the differences between a chip, microcontrollers, board, Raspberry Pi, Xiao, Seeed and many other terms that I have heard in passing but was unfamiliar with. Prior to this conversation, I did not know what was going on and where to start. Closer to the deadline, we also spent a good bit of time discussing resistors and why we needed them.

My basic circuit!

Circuits

I learned how to light up the little LED and big LED on the Seeed RP2040 board. I then learned how to use the serial monitor in the Arduino IDE. After some time, I decided I want to make a circuit with external LED that lights up either when a toggle switch is on or after sunset--this would be a step toward my final bike light project. To find the sunset time, I needed wifi access, so I switched to the Raspberry Pi Pico W. I learned that there is a "p" in Raspberry and the "W" stands for wifi!

For the circuit, I first learn to solder and to use the microscope in the Engineering Design Studio. Soldering feels quite therapeutic, and I will remember to balance my board on the headers before soldering next time. Then, I spent a few hours familiarize myself with the breadboard.

I connected a LED light and a switch to the Raspberry Pi after much help from this tutorial, Masarah from the EECS section, and staffs at EDS. See below for a more visual demonstration.

My basic circuit!

Programming in Arduino

I first read over this beginner's guide to Arduino. I then read the data sheet for RP2040 along with a data sheet tutorial and help from ChatGPT. Regardless, I am thoroughly confused by some terms whose definitions contains other terms that I don't know.

I spent a while connecting to wifi. Specifically, since I am using my phone's hotspot, I needed to enable "Maximize Compatibility" to connect with the board. Regardless, I continue to have trouble connecting to the wifi--which might be because of my hotspot more than the board.

A few weeks later, I will learn that it is indeed EDS wifi that was incompatible with my laptop. This may or may not be the root cause of my troubles.

To turn on the light after the sunset, I need to know what time does the sun sets. And to know what time the sun sets, I need to know my location dynamically. If given more them, I would implement the GoogleMap API to use wifi localization and find out my latitude and longitude; nevertheless, time was not on my side. I settled for hardcoding Cambridge's coordinates since I am very unlikely to leave campus anytime soon. Plus, the tracking location requires a constant wifi connection which is not realistic when biking.

After hardcoding the location, I generated an API key and grab the weather data from OpenWeatherMap's API, which includes sunrise and sunset data. Although my get request works in the browser and on Postman, it does not work in Arduino and returns me a status code of -2. I spent roughly 2 hours debugging this with TA Anthony, but we did not succeed. I proceed to also hardcoding the sunrise and sunset time to 6 AM and 6 PM, respectively. Below, you can see the entirety of my code, including its many bugs that are commented out.

//Anh Nguyen //September 27, 2023 //for How to Make (Almost) Anything #include #include // //wifi things const char* ssid = "INSERT YOUR WIFI NAME"; const char* password = "INSERT YOUR WIFI PASSWORD"; //default to Cambridge's coordinates; to be integrated with Google wifi localization API const double latitude = 42.3736; const double longitude = 71.1097; //api things const char* googleAPIKey = "INSERT YOUR API KEY"; const char* openWeatherMapAPIKey = "INSERT YOUR API KEY"; const char* weatherServer = "http://api.openweathermap.org"; const String endpoint = "/data/2.5/weather"; // Replace with your API endpoint const int port = 80; // HTTP port // const String getRequest = "http://api.openweathermap.org/data/2.5/weather?lat=" + String(latitude) + "&lon=" + String(longitude) + "&appid=" + String(openWeatherMapAPIKey); const String getRequest = "/data/2.5/weather?lat=" + String(latitude) + "&lon=" + String(longitude) + "&appid=" + String(openWeatherMapAPIKey); const int ledPin = 15; const int switchPinWrite = 2; const int switchPinRead = 3; const int delayTime = 1000; const int millisInDay = 1000*60*60*24; unsigned long sunrise = 1000*60*60*(6); //CHANGE AS NEEDED unsigned long sunset = sunrise + millisInDay/2; const int currentHour = 8; const int currentMin = 20; unsigned long previousMillis = ((currentHour*60 + currentMin)*60*1000); // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(ledPin, OUTPUT); pinMode(switchPinWrite, OUTPUT); pinMode(switchPinRead, INPUT); //sending voltage to write pin always digitalWrite(LED_BUILTIN, HIGH); digitalWrite(switchPinWrite, HIGH); //get time Serial.begin(9600); // // Connect to Wi-Fi // Serial.begin(115200); // delay(1000); // WiFi.begin(ssid, password); // while (WiFi.status() != WL_CONNECTED) { // delay(1000); // Serial.println("Connecting to WiFi..."); // } // Serial.println("Connected to Wi-Fi"); // //API OpenWeatherMap // Serial.println("Making API call..."); // WiFiClient client; // HttpClient http(client, weatherServer, port); // // Define the API endpoint // // Make a GET request // Serial.println(getRequest); // http.get(getRequest); // // Check the HTTP status code // int statusCode = http.responseStatusCode(); // if (statusCode == 200) { // // Read and print the response // String response = http.responseBody(); // Serial.println("Response:"); // Serial.println(response); // } else { // Serial.print("HTTP request failed with status code: "); // Serial.println(statusCode); // } } // the loop function runs over and over again forever void loop() { //reading the toggle switch int switchState = digitalRead(switchPinRead); //blink without delay unsigned long currentMillis = millis(); if (isNight(currentMillis)) { //if switch on, turn light on if (switchState == HIGH) { onLight(); Serial.println("night, light on"); } //if switch off, blink light else { blinkLight(); Serial.println("night, light blink"); } } else { //if switch on, turn light on if (switchState == HIGH) { onLight(); Serial.println("day, light on"); } //if switch off, blink light else { blinkLight(); Serial.println("day, light blink"); } } } void blinkLight() { digitalWrite(ledPin, HIGH); // turn the LED on (HIGH is the voltage level) delay(delayTime); // wait for a second digitalWrite(ledPin, LOW); // turn the LED off by making the voltage LOW delay(delayTime); // wait for a second } void onLight() { digitalWrite(ledPin, HIGH); delay(delayTime); } boolean isNight(int currentMillis) { const int currentMillisInDay = (currentMillis + previousMillis) % millisInDay; if ((currentMillisInDay > sunrise) && (currentMillisInDay < sunset)) { return false; } return true; }