Learning the board through short sketches
My CMP101 hardware work used a Wemos ESP8266 board and a collection of small peripherals. The exercises started with one input or output at a time, then combined them into a final sketch.
The archived code covers:
- switching and blinking LEDs through GPIO
- reading a push button
- sampling a potentiometer through the analogue input
- controlling a servo from serial input
- writing values to a TM1638 seven-segment display
- using the TM1638 LEDs and buttons
- displaying text on an SSD1306 OLED
- reading time from a DS3231 real-time clock
- calculating MD5 and SHA-1 digests as programming exercises
These sketches were my first direct contact with the boundary between software and hardware. A variable was no longer only internal programme state; it represented a voltage, a button level, a display segment, or a motor position.
GPIO, serial input, and direct control
The LED and button exercises established the basic Arduino structure: configure pins in setup(), then read or update hardware in loop().
A separate servo sketch used the serial monitor as its input. It waited for a numeric value, converted the text to an integer, and passed the requested angle to the servo library. The programme was simple, but the data path was complete:
- receive text over the serial connection
- parse it into a value
- apply the value to an actuator
- observe the physical result
The analogue-input exercises did the same with a potentiometer. The ESP8266 sampled the voltage at A0, converted it into an integer reading, and used that value elsewhere in the sketch.
Working with two display interfaces
The hardware kit included both an OLED and a TM1638 board. They exposed different interfaces and display models.
The SSD1306 OLED was configured over I2C at address 0x3C. The Adafruit graphics library maintained a display buffer: text was written into that buffer, display.display() transferred it to the screen, and clearDisplay() prepared the next frame.
The TM1638 board used dedicated data, clock, and strobe connections on pins D7, D6, and D5. Its library provided direct control over the seven-segment digits and LEDs, as well as access to the board’s buttons.
Using both devices in one sketch required separate initialisation, explicit cursor handling for the OLED, and decisions about which value belonged on each output.
Adding the real-time clock
The DS3231 real-time clock also used I2C. Its separate clock state allowed the sketch to request a formatted time or timestamp without relying on the ESP8266’s own uptime counter.
The early clock sketch concentrated on wiring and library calls. I then folded the RTC into the integrated hashing exercise so the display could show when an operation had run.
The archived implementation resets several clock fields before reading them, so it is not a complete clock application. It records my progression from reading one device to coordinating several libraries and buses inside the same loop.
The integrated hashing and display exercise
The final sketch brought serial input, hashing, analogue input, the RTC, OLED output, and the TM1638 display together.
It prompted for a password through the serial monitor, then calculated:
- a SHA-1 digest of the input
- a second SHA-1 digest that appended an analogue reading
- a timestamp for the operation
The OLED displayed the entered value and both digests. The TM1638 displayed the analogue sample in hexadecimal, while the real-time clock supplied a formatted time and Unix-style timestamp for a second screen.
The main flow was:
String password = Serial.readString();
String passwordHash = sha1(password);
int sensorValue = analogRead(A0);
String saltedHash = sha1(password + sensorValue);
This was a hardware-integration exercise, not a password-storage design. SHA-1 is unsuitable for storing passwords, and one analogue sample is not a robust salt or source of cryptographic randomness. The code is valuable as a record of coordinating different peripherals and moving data between input, processing, timing, and display stages.
What I would change now
The sketches use blocking reads and delays because each exercise was built around a single visible interaction. A stronger embedded design would use non-blocking timing, explicit input validation, clearer separation between device drivers and application logic, and defined error states when a peripheral is absent.
For the integrated project I would also:
- keep secrets off the display and serial console
- use a modern password-hashing design only where password storage was genuinely required
- generate random values from an appropriate source
- avoid repeatedly resetting the RTC
- represent the application as states rather than one long
loop() - document the electrical connections alongside the code
The archive shows the hardware foundation I was building in first year: GPIO, serial communication, I2C, device libraries, timing, and the practical debugging needed when software has a physical output.
