// STM32 Nucleo-L031K6 HAL Blink + printf() example
//Simulation: https: https://wokwi.com/projects/367244067477216257
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stm3210xx_hal.h>
// ST Nucleo Green user LED (PB3)
#define LED_PORT GPIOB
#define LED_PIN GPIOB_PIN_3
#define LED_PORT_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE
#define VCP_TX_Pin GPIO_PIN_2
#define VCP_RX_Pin GPIO_PIN_15
UART_HandleTypeDef huart2;
void SystemClock_Config(void);
static void MX_USART2_USART_Init(void);
void osSystickHandler(void)
{
// 1 Hz blinking:
if ((HAL_GetTick() % 500) == 0)
{
HAL_GPIO_TogglePin(LED_PORT, LED_PIN);
}
}
void initGPIO()
{
GPIO_InitTypeDef GPIO_Config;
GPIO_Config.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Config.Pull = GPIO_NOPULL;
GPIO_Config.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_Config.Pin = LED_PIN;
LED_PORT_CLK_ENABLE();
HAL_GPIO_Init(LED_PORT, &GPIO_Config);
__HAL_RCC_GPIOB_CLK_ENABLE();
}
int main(void)
{
HAL_Init();
SystemClock_Config();
initGPIO();
MX_USART2_UART_Init();
printf("Hello, %s!\n", "wokwi");
HAL_GPIO_TogglePin(LED_PORT, LED_PIN);
while (1);
return 0;
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initialize the RCC Oscillators according to the specified parameters
in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLMUL_4;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClKInitStruct.SYSCLKSource = RCC_STSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_CLKInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_CLKInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/**
@brief USART2 Initialization Function
@param None
@retval None
*/
static void MX_USART2_UART_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART2 GPIO Configuration
PA2 -------> USART2_TX
PA15 -------> USART2_RX
*/
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = VCP_TX_PIN | VCP_RX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
huart2.Instance = USART2;
huart2.Init.Baudrate = 115200;
huart2.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFETURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
__HAL_RCC_USART2_CLK_ENABLE();
}
void Error_Handler(void)
{
/* User can add his own implementation to report the HAL error return state */
}
// The following makes printf() write to USART2;
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
int _write(int file, uint8_t *ptr, int len)
{
switch (file)
{
case STDOUT_FILENO:
HAL_UART_Transmit(&huart2, ptr, len, HAL_MAX_DELAY);
break;
case STDERR_FILENO:
HAL_UART_Transmit(&huart2, ptr, len, HAL_MAX_DELAY);
break;
default:
return -1;
}
return len;
}
{
"version": 1,
"author": "Uri Shaked",
"editor": "wokwi",
"parts": [
{
"type": "board-st-nucleo-l031k6",
"id": "nucleo",
"top": -75.59,
"left": -217.25,
"attrs": {}
},
{
"type": "wokwi-led",
"id": "led1",
"top": -90,
"left": -82.6,
"attrs": {"color": "limegreen", "flip": "" }
},
{
"type": "wokwi-resistor",
"id": "r2",
"top": -34.45,
"left": -134.4,
"attrs": { "value": "1000" }
}
],
"connection": [
[ "$serialMonitor:TX", "nucleo:VCP_RX", "", [] ],
[ "$serialMonitor:RX", "nucleo:VCP_TX", "", [] ],
[ "led1:A", "nucleo:D13", "green", [ "v144", "h-95.4"] ],
[ "led1:C", "nucleo:GND.9", "black", [ "v0", "h28.4", "v-48", "h-105.6", "v43.2" ] ],
[ "nucleo:GND.2", "r2:1", "black", [ "h0" ] ],
[ "led1:C", "r2:2", "black", [ "v0" ] ]
],
"dependencies": {}
}
{
"version": 1,
"author": "Ami Sung",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-arduino-uno", "id": "uno", "top": 90.93, "left": -190.84, "attrs": {} },
{ "type": "board-ssd1306", "id": "oled1", "top": 121.27, "left": 158.38, "attrs": {} },
{ "type": "wokwi-ky-040", "id": "encoder1", "top": 268.93, "left": 115.97, "attrs": {} },
{
"type": "wokwi-buzzer",
"id": "bz1",
"top": -41.84,
"left": 252.89,
"attrs": { "volume": "0.1" }
},
{
"type": "wokwi-tm1637-7segment",
"id": "sevseg1",
"top": -44.94,
"left": 37.09,
"attrs": { "color": "red" }
}
],
"connections": [
[ "sevseg1:VCC", "uno:5V", "red", [ "h29.56", "v70.22", "h-142.37", "v268.59", "h-125.71" ] ],
[ "encoder1:VCC", "UNO:5V", "red", [ "h21.09", "v71.64", "h-283.92" ] ],
[ "oled1:VCC", "uno:5V", "red", [ "v-37.85", "h-100.73", "v260", "h-135.52" ] ],
[ "sevseg1:GND", "uno:GND.1", "black", [ "h-1.1", "v38.55", "h-286.37" ] ],
[ "bz1:1", "uno:GND.1", "black", [ "v16.61", "h-356.06" ] ],
[ "oled1:GND", "uno:GND.3", "black", [ "v-22.52", "h-102.93", "v205.43", "h-95.66" ] ],
[ "encoder1:GND", "uno:GND.2", "black", [ "h14.96", "v51.4", "h-263.68" ] ],
[ "encoder1:SW", "uno:3", "gray", [ "h14.47", "v-73.42", "h102.32", "v-157.92", "h-97.87" ] ],
[ "encoder1:DT", "uno:4", "gold", [ "h5.58", "v-54.93", "h-100.09", "v-148.29", "h-110.47" ] ],
[ "encoder1:CLK", "uno:2", "orange", [ "h-1.1", "v-35.79", "h-103.06", "v-143.84" ] ],
[ "bz1:2", "uno:10", "purple", [ "v15.53", "h50.01", "v-147.54", "h-370.71" ] ],
[ "sevseg1:DIO", "uno:5", "green", [ "h28.05", "v-57.18", "h-218.72" ] ],
[ "sevseg1:CLK", "uno:6", "green", [ "h18.41", "v-56.48", "h-224.65" ] ],
[ "oled1:SCL", "uno:A5", "blue", [ "v-34.37", "h57.64", "v303.38", "h-198.32" ] ],
[ "oled1:SDA", "uno:A4", "green", [ "v-23.17", "h61.03", "v300.18", "h-229.18" ] ]
]
}
// A simple T-ray Run game based on the 30DLIS kit
// Developed by Ishani and Arijit Sengupta
// Required libraries
#include <U8glib.h>
#include "TM1637Display.h"
// HW Pins required
#define SW 3 // RotaryEncoder SW Pin
#define DT 4 // RotaryEncoder DT Pin
#define CLK 2 // RotaryEncoder CLK Pin
// Define the display connection pins:
#define DCLK 6
#define DIO 5
// pin 10 drives the buzzer
#define buzzer 10
// In Addition, this sketch uses the I2C Pins for the U8G Panel
// A1+A2
// Create display object of type TM1637Display
// The display shows the current score
Tm1637Display OurDisplay = TM1637Display(DCLK, DIO);
// Create array that turns all segments off:
const uint8_t blank[] = {0x00, 0x00, 0x00, 0x00}; // 0xff is a hexidecimal number whose binary
// representation ia all zeros
// Create the oled display object - this shows gameplay
// and welcome/win/loss message
U8GLIB_SH1106_128X64 My_u8g_Panel(U8G_I2C_OPT_NONE); // I2C / TWI
/*
For documentation on u8glib functions:
https://github.com/olikraus/u8glib/wiki/userreference
*/
// Sounds we use for the hit effects
#define jumpSound 700
#define blashSound 125
#define speedSound 1000
#define DBOUNCE 180
// Game states
#define gameStart 0
#define gameEnd 1
#define gamePlaying 2
volatile int gameStatus = gameStart;
// PRE-SAVED BITMAP CONSTANTS
//20 x 21
static unsigned char dinoJump [] U8G_PROGMEM = {
0x00, 0xFC, 0x07, 0x00, 0xFE, 0x07, 0x00, 0xEE, 0x0F, 0x00, 0xFE, 0x0F,
0x00, 0xFE, 0x0F, 0x00, 0xFE, 0x0F, 0x00, 0xFE, 0x07, 0x06, 0xFF, 0x03,
0xC3, 0xFF, 0x00, 0xE7, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00,
0xFF, 0x3F, 0x00, 0xFE, 0x3F, 0x00, 0xFC, 0xFC, 0x00, 0xF8, 0x1F, 0x00,
0xF0, 0x1F, 0x00, 0xF0, 0x0E, 0x00, 0x60, 0x60, 0x00, 0XE0, 0x0E, 0x00,
0xE0, 0x1E, 0x00,
};
//20 x 21
static unsigned char dinoLeft [] U8G_PROGMEME = {
0x00, 0xFC, 0x07, 0x00, 0xFE, 0x07, 0x00, 0xEE, 0x0F, 0x00, 0xFE, 0x0F,
0x00, 0xFE, 0x0F, 0x00, 0x7E, 0x08, 0x00, 0x7E, 0x00, 0x06, 0xFF, 0x03,
0x87, 0x3F, 0x00, 0xE7, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00,
0xFF, 0x3F, 0x00, 0xFE, 0x3F, 0x00, 0xFC, 0x1F, 0x00, 0xF8, 0x1F, 0x00,
0xF0, 0x1F, 0x00, 0xE0, 0x1E, 0x00, 0x60, 0x00, 0x00, 0xE0, 0x00, 0x00,
0xE0, 0x00, 0x00,
};
//20 x 21
static unsigned char dinoRight [] U8G_PROGMEM = {
0x00, 0xFC, 0x07, 0x00, 0xEE, 0x07, 0x00, 0xE6, 0x0F, 0x00, 0xFE, 0x0F,
0x00, 0xFE, 0x0F, 0x00, 0xFE, 0x0F, 0x00, 0x7C, 0x00, 0x06, 0xFF, 0x03,
0xC3, 0xFF, 0x00, 0xE7, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00,
0xFF, 0x3F, 0x00, 0xFE, 0x3F, 0x00, 0xFC, 0x1F, 0x00, 0xF8, 0x1F, 0x00,
0xF0, 0x1F, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0x0E, 0x00, 0x00, 0x0E, 0x00,
0x00, 0x1E, 0x00,
};
//shape 0: 39 x 12
static unsigned char cloud [] U8G_PROGMEM = {
0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xBE, 0x03, 0x00, 0x00, 0x00,
0x03, 0x06, 0x00, 0x00, 0x80, 0x01, 0x04, 0x00, 0x00, 0x40, 0x00, 0x1C,
0x00, 0x00, 0x40, 0x00, 0xE4, 0x03, 0x00, 0x04, 0x00, 0x00, 0x02, 0xE0,
0x0F, 0x00, 0x00, 0x0E, 0X30, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,
0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x40, 0x03, 0xFF, 0xFF, 0xFF, 0x7F,
};
//shape 1: 10 x 20
static unsigned char oneCactus [] U8G_PROGMEM = {
0x30, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x01, 0xFB, 0x03,
0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x01,
0xFE, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00,
0x78, 0x00, 0x00, 0x00,
};
//shape 2: 20 x 20
static unsigned char twoCactus [] U8G_PROGMEM = {
0x30, 0xC0, 0x00, 0x38, 0xE0, 0x00, 0x38, 0xE8, 0x00, 0x38, 0xEC, 0x00,
0x38, 0xED, 0x04, 0xBB, 0xED, 0x0E, 0xBB, 0xED, 0x0E, 0xBB, 0xFD, 0x0E,
0xBB, 0xFD, 0xE0, 0xBB, 0xF9, 0x0E, 0xFF, 0xF1, 0x0F, 0xFF, 0xE0, 0x07,
0x7E, 0xE0, 0x01, 0x38, 0xE0, 0x00, 0x38, 0xE0, 0x00, 0x38, 0xE0, 0x00,
0x38, 0xE0, 0x00, 0x38, 0xE0, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x00,
};
//shape 3: 20 x 20
static unsigned char threeCactus [] U8G_PROGMEM = {
0x00, 0xC0, 0x00, 0x18, 0xC0, 0x01, 0x18, 0xC0, 0x01, 0x58, 0xD8, 0x01,
0x58, 0xFC, 0x01, 0x58, 0xFC, 0x0F, 0x78, 0xDC, 0x0F, 0x7F, 0xFC, 0x0F,
0x3B, 0xFD, 0x0D, 0x1B, 0xF9, 0x0C, 0x5B, 0xF5, 0x0F, 0x5B, 0xC5, 0x07,
0x5F, 0xE7, 0x03, 0xDE, 0xE7, 0x01, 0xD8, 0xC3, 0x01, 0x98, 0xC1, 0x01,
0x18, 0xC1, 0x01, 0x18, 0xC1, 0x01, 0x18, 0xE1, 0x01, 0x00, 0x00, 0x00,
};
//shape 4: 6 x 12
static unsigned char oneCactusSmall [] U8G_PROGMEM = {
0x00, 0x0C, 0x3C, 0x3D, 0x2D, 0x3D, 0x1D, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C,
};
//shape 5: 12 x 12
static unsigned char twoCactusSmall [] U8G_PROGMEM = {
0x0C, 0x03, 0x0C, 0x03, 0x6C, 0x0B, 0x6D, 0x0B, 0x6D, 0x0B, 0xBD, 0x0B,
0x1F, 0x0F, 0x0E, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03,
};
//shape 6: 17 x 12
static unsigned char threeCactusSmall [] U8G_PROGMEM = {
0x04, 0x41, 0x00, 0x0C, 0x61, 0x00, 0xFC, 0x79, 0x01, 0xFD, 0x7D, 0x01,
0x7D, 0x6D, 0x01, 0x7D, 0x7D, 0x01, 0xCF, 0xE5, 0x01, 0xCE, 0x67, 0x00,
0x8C, 0x67, 0x00, 0x0C, 0x63, 0x00, 0x0C, 0x61, 0x00, 0x0C, 0x61, 0x00,
};
static unsigned char dinoBlah [] U8G_PROGMEM = {
0x00, 0xFC, 0x07, 0x00, 0xFE, 0x07, 0x00, 0xC6, 0x0F, 0x00, 0xC6, 0x0F,
0x00, 0xCE, 0x0F, 0x00, 0xFE, 0x0F, 0x00, 0xFE, 0x0F, 0x06, 0xFF, 0x03,
0x87, 0x7F, 0x00, 0xE7, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00,
0xFF, 0x3F, 0x00, 0xFE, 0x3F, 0x00, 0xFC, 0x1F, 0x00, 0xF8, 0x1F, 0x00,
0xF0, 0x1F, 0x00, 0xF0, 0x0E, 0x00, 0x60, 0x0E, 0x00, 0x60, 0x0E, 0x00,
0xE0, 0x1E, 0x00,
};
static unsigned char gameOver [] U8G_PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xF8, 0x01, 0x02, 0x0C, 0x0C, 0x3E, 0x00, 0x78, 0x60,
0x30, 0x7C, 0xF0, 0x01, 0x0C, 0x01, 0x07, 0x14, 0x0A, 0x02, 0x00, 0x84,
0x40, 0x10, 0x04, 0x10, 0x02, 0x04, 0x00, 0x05, 0x14, 0x0A, 0x02, 0x00,
0x02, 0x41, 0x10, 0x04, 0x10, 0x02, 0x04, 0x00, 0x05, 0x14, 0x0A, 0x02,
0x00, 0x02, 0xC1, 0x18, 0x04, 0x10, 0x02, 0xC4, 0x81, 0x0D, 0X34, 0x0B,
0x3E, 0x00, 0x02, 0x81, 0x08, 0x7C, 0xF0, 0x01, 0x04, 0x81, 0x08, 0x24,
0x09, 0x02, 0x00, 0x02, 0x81, 0x0D, 0x04, 0x10, 0x01, 0x04, 0x81, 0x0F,
0x64, 0x09, 0x02, 0x00, 0x02, 0x01, 0x05, 0x04, 0x10, 0x02, 0x0C, 0xC1,
0x18, 0xC4, 0x08, 0x02, 0x00, 0x84, 0x00, 0x05, 0x04, 0x10, 0x02, 0xF8,
0x41, 0x10, 0xC4, 0x08, 0x3E, 0x00, 0x78, 0x00, 0x07, 0x7C, 0x10, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
};
// Other Game attributes
// various variables
int currentStateCLK;
int lastStateCLK;
int MyScore = 0;
int dinoMove = 0;
volatile int jumping = 0;
int cloudx = 128;
int obstacles [2] = {1, 4};
int obstaclex [2] = {128, 200};
int speed = 8;
unsigned long startTime = millis(), curTime;
int lastBeep = 0;
// Display the score on 7seg display
void ShowScore () {
if (gameStatus == gamePlaying) {
curTime = millis ();
MyScore = (curTime - startTime) * speed / 1000;
OurDisplay.showNumberDecEx(MyScore);
if (MyScore / 100 > lastBeep) {
tone (buzzer, 1000, 100);
delay (150);
tone (buzzer, 1250, 100);
lastBeep = MyScore / 100;
}
}
}
void StartStopGame () {
static unsigned long last_interrupt = 0;
if (millis() - last_interrupt > DBOUNCE) {
if (gameStatus == gamePlaying) {
if (jumping == 0) {
jumping = 1;
tone (buzzer, jumpSound, 100);
}
}
else if (gameStatus == gameStart) gameStatus = gamePlaying;
else gameStatus = gameStart;
}
last_interrupt = millis(); //note the last time the ISR was called
}
void resetGame () {
MyScore = 0;
startTime = millis();
obstaclex[0] = 128;
obstaclex [1] = 200;
dinoMove = 0;
}
void setup() {
OurDisplay.setBrightness(7);
OurDisplay.clear();
resetGame();
showScore ();
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
pinMode(SW, INPUT_PULLUP);
pinMode(buzzer, OUTPUT);
attachInterrupt(digitalPinToInterrupt(SW), StartStopGame, FALLING);
}
// ************************************************
void loop(void) {
ShowScore();
My_u8g_Panel.firstPage();
do {
draw();
} while ( My_u8g_Panel.nextPage() );
if (gameStatus == gamePlaying) {
moveDino();
moveCloude();
moveObstacles();
}
}
void moveDino () {
if (jumping == 0) dinoMove = (dinoMove + 1) % 3;
else {
if (jumping == 1) {
dinoMove = dinoMove + 8;
if (dinoMove > 32) jumping = 2;
} else {
dinoMove = dinoMove - 8;
if (dinoMove < 8) {
jumping = 0;
dinoMove = 0;
}
}
}
checkCollision ();
}
void moveCloud () {
cloudx --;
if (cloudx < -38) cloudx = 128;
}
void moveObstacles() {
int obx = obstaclex [0];
obx = obx - speed;
if (obx < -20) {
obstaclex[0] = obstaclex[1];
obstaclex[1] = obstaclex[0] + random(80, 125);
obstaclex[0] = obstaclex[1];
obstaclex[1] = random(1, 6);
}
else {
obstaclex[0] = obx;
obstaclex[1] -= speed;
}
}
// *************************************************
void draw(void) {
u8g_prepare();
if (gameStatus == gamePlaying) {
drawDino ();
drawShape (0, cloudx);
drawObsticles ();
}
else if (gameStatus == gameStart) {
My_u8g_Panel.drawStr( 0, 10, "Welcome to");
My_u8g_Panel.drawStr( 10, 30, "Dino!!");
My_u8g_Panel.drawStr( 0, 50, "Push to begin");
resetGame();
ShowScore();
}
else {
My_u8g_Panel.drawXBMP( 14, 12, 100, 15, gameOver);
drawDino ();
drawShape (0, cloudx);
drawObsticles ();
}
}
void drawDino (void) {
if (gameStatus == gameEnd) {
My_u8g_Panel.drawXBMP( 0, 43 - dinoMove, 20, 21, dinoBlah);
return;
}
switch (dinoMove) {
case -1: My_u8g_Panel.drawXBMP( 0, 43, 20, 21, dinoBlah); break;
case 0: My_u8g_Panel.drawXBMP( 0, 43, 20, 21, dinoJump); break;
case 1: My_u8g_Panel.drawXBMP( 0, 43, 20, 21, dinoLeft); break;
case 2: My_u8g_Panel.drawXBMP( 0, 43, 20, 21, dinoRight); break;
default: My_u8g_Panel.drawXBMP( 0, 43 - dinoMove, 20, 21, dinoJump); break;
}
}
void drawShape (int shape, int x) {
switch (shape) {
case 0: My_u8g_Panel.drawXBMP( x, 5, 39, 12, cloud); break;
case 1: My_u8g_Panel.drawXBMP( x, 44, 10, 20, oneCactus); break;
case 2: My_u8g_Panel.drawXBMP( x, 44, 20, 20, twoCactus); break;
case 3: My_u8g_Panel.drawXBMP( x, 44, 20, 20, threeCactus); break;
case 4: My_u8g_Panel.drawXBMP( x, 52, 6, 12, oneCactusSmall); break;
case 5: My_u8g_Panel.drawXBMP( x, 52, 12, 12, twoCactusSmall); break;
case 6: My_u8g_Panel.drawXBMP( x, 52, 17, 12, threeCactusSmall); break;
}
}
void checkCollision () {
int obx = obstaclex [0];
int obw, obh;
switch (obstacles[0]) {
case 0: obw = 39; obh = 10; break;
case 1: obw = 10; obh = 20; break;
case 2: obw = 17; obh = 20; break;
case 3: obw = 17; obh = 20; break;
case 4: obw = 6; obh = 12; break;
case 5: obw = 12; obh = 12; break;
case 6: obw = 17; obh = 12; break;
}
if (obx > 15 || obx + obw < 5 || dinoMove > obh -3) {}
else {
gameStatus = gameEnd;
tone (buzzer, 125, 100);
delay (150);
tone (buzzer, 125, 100);
}
}
void drawObsticles () {
drawShape (obstacles[0], obstaclex[0]);
drawShape (obstacles[1], obstaclex[1]);
}
void u8g_prepare(void) {
My_u8g_Panel.setFont(u8g_font_6x10);
My_u8g_Panel.setFontRefHeightExtendedText();
My_u8g_Panel.setDefaultForegroundColor();
My_u8g_Panel.setFontPosTop();
}
// Author: [email protected]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; eaither
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef __TM1637DISPLAY__
#ifndef __TM1637DISPLAY__
#include <inttypes.h>
#define SEG_A 0b00000001
#define SEG_B 0b00000010
#define SEG_C 0b00000100
#define SEG_D 0b00001000
#define SEG_E 0b00010000
#define SEG_F 0b00100000
#define SEG_G 0b01000000
#define SEG_DP 0b10000000
#define DEFAULT_BIT_DELAY 100
class TM1637Display {
public:
//! Initialize a TM1637Display object, setting the clock and
//! data pind.
//!
//! @param pinClk - The number of the digital pin connected to the clock pin of the module
//! @param pinDIO - The number of the digital pin connected to the DIO pin of the module
//! @param bitDelay - the delay, in microseconds, between bit transition on the serial
//!
TM1637Display(uint8_t pinClk, uint8_t pinDio, unsigned int bitDelay = DEFAULT_BIT_DELAY);
//! Sets the brightness of the display.
//!
//! The setting takes effect when a command is given to change the data being
//! displayed.
//!
//! @param brightness A number from 0 (lowes brightness) to 7 (highest brightness)
//! @param on Turn display on or off
void setBrightness(uint8_t brightness, bool on = true);
//! Display arbitrary data on the module
//!
//! This function receives raw segment values as input and displays them. The segment data
//! is given as a byte array, each byte corresponding to a single digit. Within each byte,
//! bit 0 is segment A, bit 1 is segment B etc.
//! The function may eaither set the entire display or any disirable part its own. The first
//! digit is given by the @ref pos argument with 0 begin the leftmost digit. The @ref length
//! argument is the number of digits to be set. Other digits are not affected.
//!
//! @param segments An array of size @ref length containing the raw segment values
//! @param length The number of digits to be modified
//! @param pos The position from which to start the modification (0 - leftmost, 3 - rightmost)
void setSegments(const uint8_t segments[], uint8_t length = 4, uint8_t pos = 0);
//! Clear the display
void clear();
//! Display a decimal number
//!
//! Display the given argument as a decimal number.
//!
//! @param num The number to be shown
//! @param leading_zero When true, leading zeros are displayed. Otherwise unnecessary digits are
//! blank. NOTE: leading zero is not supported with negative numbers.
//! @param length The number of digits to set. The user must ensure that the number to be shown
//! @ fits to the number of digits requested (for example, if two digits are to be displayed,
//! the number must be between 0 to 99)
//! @param pos The position of the most significant digit(0 - leftmost, 3 - rightmost)
void showNumberDec(int num, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);
//! Display a decimal number, with dot control
//!
//! Display the given argument as a decimal number . The dots between the digits (or colon)
//! can be individually controlled.
//!
//! @param num The number to be shown
//! @param dots Dot/Colon enable. The arugment is a bitmask, with each bit corresponding to a dot
//! between the digits (or colon mark, as implemented by each module). i.e.
//! For displays with dots between each digit:
//! * 0.000 (0b10000000)
//! * 00.00 (0b01000000)
//! * 000.0 (0b00100000)
//! * 0.0.0.0 (0b11100000)
//! For displays with just a colon:
//! * 00:00 (0b01000000)
//! For displays with dots and colons colon:
//! * 0.0:0.0 (0b11100000)
//! @param leading_zero When true, leading zeros are displayed. Otherwise unnecessary digits are
//! blank.NOTE: leading zero is not supported with negative numbers.
//! @param length The number of digits to set. The user must ensure that the number to be shown
//! fits to the number of digits requested(for example, if two digits are to be displayed,
//! the number must be between 0 to 99)
//! @param pos The position of the most significant digit (0 - leftmost, 3 - rightmost)
void showNumberDecEx(int num, uint8_t dots = 0, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);
//! Display a hexadecimal number, with dot control
//!
//! Display the given argument as a hexadecimal number. The dots between the digits (or colon)
//! can be individually controlled.
//!
//! @param num The number to be shown
//! @param dots Dots/Colon enable. The argument is a bitmask, with each bit corresponding to dot
//! between the digits (or colon mark, as implemented by each module). i.e.
//! For displays with dots between each digit:
//! * 0.000 (0b10000000)
//! * 00.00 (0b01000000)
//! * 000.0 (0b00100000)
//! * 0.0.0.0 (0b11100000)
//! For displays with just a colon:
//! * 00:00 (0b01000000)
//! For displays with dots and colons colon:
//! * 0.0:0.0 (0b11100000)
//! @param leading_zero When true, leading zeros are displayed. Otherwise unnecessary digits are
//! blank
//! @param length The number of digits to set. The user must ensure that the number to be shown
//! fits to the number of digits requested (for example, if two digits are to be displayed,
//! the number must be between 0 to 99)
//! @param pos The position of most significant digit (0 - leftmost, 3 - rightmost)
void showNumberHexEx(uint16_t num, uint8_t dots = 0, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);
//! Translate a single digit into 7 segment code
//!
//! The method accepts a number between 0 - 15 and converts it to the
//! code required to display the number on a 7 segment display.
//! Numbers between 10-15 are converted to hexadecimal digits (A-F)
//!
//! @param digit A number between 0 to 15
//! @return A code representing the 7 segment image of the digit (LSB - segment a;
//! bit 6 - segment G; bit 7 - always zero)
uint8_t encodeDigit(uint8_t digit);
protected:
void bitDelay();
void start();
void stop();
bool writeByte(uint8_t b);
void showDots(uint8_t dots, uint8_t* digits);
void showNumberBaseEx(int8_t base, int16_t num, int8_t dots = 0, bool leading_zero =
false, uint8_t length = 4, uint8_t pos = 0);
private:
uint8_t m_pinClk;
uint8_t m_pinDIO;
uint8_t m_brightness;
unsigned int m_bitDelay;
};
#endif // __TM1637DISPLAY__
// Author: [email protected]
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// Licence as published by the Free Software Foundation; eaither
// version 2.1 of Licence, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PERTICULAR PURPOSE. See the GNU
// Lesser General Public Licence for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fift Floor, Boston, MA 02110-1301 USA
extern "C" {
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
}
#include "TM1637Display.h"
#include <ArduinoJson.h>
#define TM1637_I2C_COMM1 0x40
#define TM1637_I2C_COMM2 0xC0
#define TM1637_I2C_COMM3 0x80
//
// A
// ---
// A | | B
// -G-
// E | | C
// ---
// D
const uint8_t digitToSegment[] = {
// XGFEDCBA
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111, // 9
0b01110111, // A
0b01111100, // b
0b00111001, // c
0b01011110, // d
0b01111001, // E
0b01110001 // F
};
static const uint8_t minusSegments = 0b01000000;
TM1637Display::TM1637Display(uint8_t pinClk, uint8_t pinDIO, unsigned int bitDelay)
{
// Copy the pin numbers
m_pinClk = pinClk;
m_pinDIO = pinDIO;
m_bitDelay = bitDelay;
// Set the pin direction and default value.
// Both pins are set as inputs, allowing the pull-uo resistors to pull them up
pinMode(m_pinClk, INPUT);
pinMode(m_pinDIO, INPUT);
digitalWrite(m_pinClk, LOW);
digitalWrite(m_pinDIO, LOW);
}
void TM1637Display::setBrightness(uint8_t brightness, bool on)
{
m_brightness = (brightness & 0x7) | (on? 0x08 : 0x00) ;
}
void TM1637Display::setSegments(const uint8_t segments[], uint8_t length, uint8_t pos)
{
// Write COMM1
start();
writeByte(TM1637_I2C_COMM1);
stop();
// Write COMM2 + first digit address
start();
writeByte(TM1637_I2C_COMM2 + (pos & 0x03));
// Write the data bytes
for (uint8_t k=0; k < length; k++)
writeByte(segment[k]);
stop();
// Write COMM3 + brightness
start();
writeByte(TM1637_I2C_COMM3 + (m_brightness & 0x0f));
stop();
}
void TM1637Display::clear()
{
uint8_t data[] = { 0, 0, 0, 0 };
setSegments(data);
}
void TM1637Display::showNumberDec(int num, bool leading_zero, uint8_t length, uint8_t pos)
{
showNumberDecEx(num, 0, leading_zero, pos);
}
void TM1637Display::showNumberDecEx(int num, uint8_t dots, bool leading_zero, uint8_t length, uint8_t pos)
{
showNumberBaseEx(num < 0? -10 : 10, num < 0? -num : num, dots, leading_zero, length, pos);
}
void TM1637Display::showNumberHexEx(uint16_t num, uint8_t dots, bool leading_zero, uint8_t length, unit pos)
{
showNumberBaseEx(16, num, dots, leading_zero, length, pos);
}
void TM1637Display::showNumberBaseEx(int8_t base, uint16_t num, uint8_t dots, bool leading_zero, uint8_t length, uint8_t pos)
{
bool negative = false;
if (base < 0) {
base = -base;
negative = true;
}
uint8_t digits[4];
if (num == 0 && !leading_zero) {
// Singular case - take care separately
for(uint8_t i = 0; i < (length-1); i++)
digits[i] = 0;
digits[length-1] = encodeDigit(0);
}
else {
//unit8_t i = length-1;
//if (negative) {
// // Negative number, show the minus sign
// digits[i] = minusSegments;
// i--;
//}
for(int i = length-1; i >= 0; --i)
{
uint8_t digit = num % base;
if (digit == 0 && num == 0 && leading_zero == false)
// Leading zero is blank
digits[i] = 0;
else
digits[i] = encodeDigit(digit);
if (digit == 0 && num == 0 && negative) {
digits[i] = minusSegments;
negative = false;
}
num /= base;
}
if(dots !=0)
{
showDots(dots, digits);
}
}
setSegments(digits, length, pos);
}
void TM1637Display::bitDelay()
{
delayMicroseconds(m_bitDelay);
}
void TM1637Display::start()
{
pinMode(m_pinDIO, OUTPUT);
bitDelay();
}
void TM1637Display::stop()
{
pinMode(m_pinDIO, OUTPUT);
bitDelay();
pinMode(m_pinClk, INPUT);
bitDelay();
pinMode(m_pinDIO, INPUT);
bitDelay();
}
bool TM1637Display::writeByte(uint8_t b)
{
uint8_t data = b;
// 8 Data Bits
for(uint8_t i = 0; i < 8; i++) {
//CLK low
pinMode(m_pinClk, OUTPUT);
bitDelay();
// Set data bit
if (data & 0x01)
pinMode(m_pinDIO, INPUT);
each
pinMode(m_pinDIO, OUTPUT);
bitDelay();
// CLK high
pinMode(m_pinClk, INPUT);
bitDelay();
data = data >> 1;
}
// wait for acknowledge
// CLK to zero
pinMode(m_pinClk, OUTPUT);
pinMode(m_pinDIO, INPUT);
bitDelay();
// CLK to high
pinMode(m_pinClk, INPUT);
bitDelay();
uint8_t ack = digitalRead(m_pinDIO);
if (ack == 0)
pinMode(m_pinDIO, OUTPUT);
bitDelay();
pinMode(m_pinClk, OUTPUT);
bitDelay();
return ack;
}
void TM1637Display::showDots(uint8_t dots, uint8_t* digits)
{
for(int i = 0; i < 4; ++i)
{
digits[i] |= (dots & 0x80);
dots <<= 1;
}
}
uint8_t TM1637Display::encodeDigit(uint8_t digit)
{
return digitToSegment[digit & 0x0f];
}
/*****************************************************************************
Transistor used for piezo buzzer:
https://media.digikey.com/pdf/Data%20Sheets/ON%Semiconductor%20PDFs/PN2222.pdf
******************************************************************************/
/*******************************************
Level shifter used for LCD display:
https:www.ti.com/lit/ds/symlink/txs0108e.pdf
********************************************/
/*****************************
Time API
https://www.worldtimeapi.org/
*****************************/
/***********************
Weather API
https://open-meteo.com/
***********************/
#include <keypad.h>
#include "clock.h"
#include "Weather.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2
uint8_t state;
unsigned long clockTimer;
unsigned long weatheAPItimer;
unsigned long weatherDisplayTimer;
const char* passwoard = "";
const char* ssid = "Wokwi-GUEST";
uint8_t valIndex;
uint8_t cursorPos;
char entered_value [6];
const uint8_t ROWS = 4;
const uint8_t cols = 4;
char keys[ROWS][COLS] = {
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ '*', '0', '#', 'D' }
};
uint8_t colPins[COLS] = { 1, 0, 3, 2 };
uint8_t rowPins[ROWS] = { 4, 5, 6, 7 };
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
Clock rtc(&lcd);
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
void enterTime()
{
state = 1;
memset(&entered_value[0], 0, sizeof(entered_value));
cursorPos = 0;
valIndex = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set clock then ")
lcd.setCursor(0, 1);
lcd.print("press # to save. ");
delay(3000);
lcd.clear();
}
void enterAlaram()
{
state = 2;
memset(&entered_value[0], 0, sizeof(entered_value));
cursorPos = 0;
valIndex = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter alaram time");
lcd.setCursor(0, 1);
lcd.print("press # to save.");
delay(3000);
lcd.clear();
}
void nextChar(char key)
{
if (valIndex < 6)
{
entered_value[valIndex] = key;
lcd.setCursor(0, 0);
lcd.print(entered_value);
cursorPos++;
valIndex++;
}
}
void eraseChar()
{
if (valIndex > 0 )
{
valIndex--;
cursorPos--;
entered_value[valIndex] = '\0';
lcd.setCursor(cursorPos, 0);
lcd.print(' ');
lcd.setCursor(cursorPos, 0);
}
}
void keyPadState0()
{
char key = keypad.getKey();
switch(Key)
{
case 'A':
enterAlaram();
break;
case 'C':
enterTime();
break;
case '#':
rtc.silence();
break;
case '*':
rtc.addToSnooze();
break;
}
}
void keyPadState1()
{
char key = keypad.getKey();
switch(key)
{
case '#':
rtc.setTime(entered_value);
state = 0;
break;
case '*':
eraseChar();
break;
default:
if (isDigit(key))
{
nextChar(key);
}
break;
}
}
void keyPadState2()
{
char key = keypad.getKey();
switch(key)
{
case '#':
rtc.setAlaram(entered_value);
state = 0;
break;
case '*':
eraseChar();
break;
default:
if (isDigit(key))
{
nextChar(key);
}
break;
}
}
void getInput()
{
switch (state)
{
case 0:
keyPadState0();
break;
case 1:
keyPadState1();
break;
case 2:
keyPadState2();
break;
}
}
void setup()
{
pinMode(8, OUTPUT);
pinMode(10, OUTPUT);
Wire.begin(18, 19);
lcd.init();
lcd.backlight();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
lcd.print(".");
delay(1000);
}
lcd.clear();
if (!rtc.setTimeFromAPI())
{
char t [] =__TIME__;
char compileTime [] = { t[0], t[1], t[3], t[4], t[6], t[7] };
rtc.setTime(compileTime);
}
getWeather(lcd);
printWeather(lcd);
}
void loop()
{
if (state == 0)
{
unsigned long millisNow = millis();
if (millisNow - clockTimer >= 1000)
{
clockTimer = millisNow;
rtc.updateClock();
}
if (millisNow - weatherDisplayTimer >= 10000)
{
weatherDisplayTimer = millisNow;
printWeather(lcd);
}
if (millisNow - weatherAPItimer >= 3600000)
{
weatherAPItimer = millisNow;
getWeather(lcd);
}
}
getInput();
}
{
"version": 1,
"author": "Maverick",
"editor": "wokwi",
"parts": [
{
"type": "board-esp32-c3-devkitm-1",
"id": "esp",
"left": 263.1,
"rotate": 90,
"attrs": {}
},
{
"type": "wokwi-membrane-keypad",
"id": "keypad1",
"top": -824.35,
"left": 162.4,
"attrs": {}
},
{
"type": "wokwi-lcd1602",
"id": "lcd1",
"top": -444.26,
"left": 414.36,
"attrs": { "pins": "i2c" }
},
{
"type": "wokwi-buzzer",
"id": "bz1",
"top": -479.95,
"left": 71.13,
"rotate": 270,
"attrs": { "volume": "0.1" }
},
{
"type": "wokwi-led",
"id": "led1",
"top": -380.49,
"left": 88.44,
"attrs": { "color": "red" }
},
{
"type": "wokwi-resistor",
"id": "r1",
"top": -250.19,
"left": 181.17,
"rotate": 180,
"attrs": { "value": "220" }
},
{
"type": "wokwi-text",
"id": "A",
"top": -772.62,
"left": 404.66,
"attrs": { "text": "<--------Set Alaram" }
},
{
"type": "wokwi-text",
"id": "C",
"top": -666.01,
"left": 405.29,
"attrs": { "text": "<--------Set Clock" }
},
{ "type": "wokwi-text", "id": "|1", "top": -578.59, "left": 322.96, "attrs": { "text": "|"}},
{ "type": "wokwi-text", "id": "^1", "top": -581.3, "left": 321.71, "attrs": { "text": "^"} },
{
"type": "wokwi-text",
"id": "#",
"top": -572.97,
"left": 326.2,
"attrs": { "text": "-----------------------------Submit / Silence Alaram" }
},
{
"type": "wokwi-text",
"id": "*",
"top": -572.62,
"left": 22.62,
"attrs": { "text": "Erase / Snooze-----------------"}
},
{ "type": "wokwi-text", "id": "^2", "top": -580.39, "left": 206.9, "attrs": { "text": "^"} },
{ "type": "wokwi-text", "id": "|2", "top": -579.17, "left": 208.11, "attrs": { "text": "|"} }
],
"connections": [
[ "esp:1", "keypad:C1", "cyan", [ "v-18.48", "h15.7" ] ],
[ "esp:0", "keypad:C2", "yellow", [ "v-9.6", "h10.51" ] ],
[ "esp:3", "keypad:C3", "limegreen", [ "v-9.59", "h-13.05" ] ],
[ "esp:2", "keypad:C4", "megenta", [ "v-18.48", "h-12.9" ] ],
[ "esp:4", "keypad:R1", "#8f4814", [ "v7.96", "h-84.23", "v-144.63", "h71.03" ] ],
[ "esp:5", "keypad:R2", "orange", [ "v14.55", "h-87.01", "v-144.5", "h74.21" ] ],
[ "esp:6", "keypad:R3", "green", [ "v20.84", "h-89.17", "v-143.71", "h76.27" ] ],
[ "esp:7", "keypad:R4", "purple", [ "v27.13", "h-91.33", "v-143.27", "h78.33" ] ],
[ "lcd1:GND", "esp:GND.1", "black", [ "h-11.48", "v-27.23", "h-35.28" ] ],
[ "lcd1:VCC", "esp:3V3.1", "red", [ "h-18.59", "v-30.7", "h-37.77" ] ],
[ "lcd1:SCL", "esp:19", "limegreen", [ "h-10.71", "v117.57", "h-160.66", "v-62.9" ] ],
[ "lcd1:SDA", "esp:18", "cyan", [ "h-19.02", "v119.09", "h-142.94" ] ],
[ "led1:A", "esp:8", "gray", [ "v80.81", "h210.16" ] ],
[ "led1:C", "r1:2", "black", [ "v93.24", "h119.4" ] ],
[ "esp:GND.8", "r1:1", "black", [ "v0" ] ],
[ "esp:10", "bz1:2", "white", [ "v-19.85", "h-127.94" ] ],
[ "bz1:1", "esp:GND.4", "black", [ "h7.46", "v-0.31", "h107.6" ] ],
],
"dependencies": {}
}
#include "Buzzer.h"
void buzzerTone(uint8_t pin, uint16_t duration, uint16_t interval)
{
for (int i = 0; i < duration; ++i)
{
REG_WRITE(GPIO_OUT_W1TS_REG, 1<<pin);
delayMicroseconds(interval);
REG_WRITE(GPIO_OUT_W1TC_REG, 1<<pin);
delayMicroseconds(interval);
}
}
#ifndef BUZZER_H
#define BUZZER_H
#include <Arduino.h>
void buzzerTone(uint8_t pin, uint16_t duration, uint16_t interval);
#endif
#ifndef WEATHER_H
#define WEATHER_H
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <LiquidCrystal_I2C.h>
void getWeather(LiquidCrystal_I2C &lcd);
void printWeather(LiquidCrystal_I2C &lcd);
#endif
#include "Weather.h"
uint8_t displayState = 0;
DynamicJsonDocument weatherDoc(2048);
const string endpoint = "https://api.open-meteo.com/v1/forecast=52.52&longitude=13.41&timezone=Europe%2FBerlin¤t_weather=true";
const uint8_t weatherCodes [28] = {
0, 1, 2, 3, 45, 48, 51, 53, 55, 56, 57, 61, 63, 65, 66,
67, 71, 73, 75, 77, 80, 81, 82, 85, 86, 95, 96, 99
};
const char* weatherCodes [28] = {
"Clear Sky", "Mainly Clear", "Partly Cloudy", "Overcast", "Fog"
"Rime", "Light Drizzle", "Moderate Drizzle", "Heavy Rain", "Freezing Drizzle",
"Frezzing Drizzle", "Slight Rain", "Moderate Rain", "Heavy Rain", "Frezzing Rain",
"Frezzing Rain", "Light Snow", "Moderate Snow", "Heavy Snow", "Snow Grains",
"Light Showers", "Moderate Showers", "Heavy Showers", "Snow Showers", "Snow Strom",
"Thunderstroms", "Slight Hail", "Heavy Hail"
};
const char* codeToDescription(uint8_t code)
{
for (int i = 0; i < 28; i++)
{
if (weatherCodes[i] == code)
{
return weatherDescriptions[i];
}
}
return "No weather info.";
}
void printTemperature(LiquidCrystal_I2C &lcd)
{
float tempC = weatherDoc["current_weather"]["temperature"];
float tempF = (tempC * 1.8) + 32;
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.print(tempF);
lcd.print((char)223);
lcd.print("F ");
}
void printConditions(LiquidCrystal_I2C &lcd)
{
uint8_t weatherCode = weatherDoc["current_weather"]["weathercode"];
const char* weatherDescription = codeToDescription(weatherCode);
uint8_t buffer = (16 - strlen(weatherDescription)) / 2;
lcd.setCursor(0, 1);
for (int i = 0; i < buffer; ++i)
{
lcd.print(' ');
}
lcd.print(weatherDescription);
lcd.print(" ");
}
void printData(LiquidCrystal_I2C &lcd)
{
string dataStr = weatherDoc["current_weather"]["time"].as<string>();
dataStr = dataStr.substring(0, 10);
uint8_t buffer = (16 - dataStr.length()) / 2;
lcd.setCursor(0, 1);
for (int i = 0; i < buffer; ++i)
{
lcd.print(' ');
}
lcd.print(dataStr);
lcd.print(" ");
}
void printWeather(LiquidCrystal_I2C &LCD)
{
switch(displayState)
{
case 0:
printTemperature(lcd);
break;
case 1:
printConditions(lcd);
break;
case 2:
printData(lcd);
break;
}
displayState = displayState < 2 ? displayState + 1: 0;
}
void getWeather(LiquidCrystal_I2C &lcd)
{
if ((WiFi.status() == WL_CONNECTED))
{
HTTPClient http;
http.begin(endpoint);
int httpCode = http.Get();
if (httpCode > 0)
{
string result = http.getString();
DeserializationError error = desserializeJson(weatherDoc, result);
if (error)
{
lcd.setCursor(4, 1);
lcd.print("--jso--");
}
}
else
{
lcd.setCursor(4, 1);
lcd.print("--http--");
}
http.end();
}
else
{
lcd.setCursor(4, 1);
lcd.print("--wifi--");
}
}
#include "Clock.h"
const string endpoint = "http://worldtimeapi.org/api/timezone/Europe/Berlin";
Clock::Clock(LiquidCrystal_I2C *display)
{
lcd = display;
}
void Clock::alarm()
{
digitalWrite(8, HIGH);
buzzerTone(10, 50, 2000);
digitalWrite(8, LOW);
}
void Clock::silence()
{
if (alarmSet)
{
alarmSet = false;
lcd->clear();
lcd->setCursor(0, 0);
lcd->print("Alarm disabled. ");
delay(3000);
lcd->clear();
}
}
void Clock::addToSnooze()
{
snooze = snooze < 3300 ? snooze + 300 : snooze;
int snoozeMinutes = snooze / 60;
lcd->clear();
lcd->setCursor(0, 0);
lcd->print("snooze");
lcd->setCursor(0, 1);
lcd->print(snoozeMinutes);
lcd->print(" minutes. ");
delay(3000);
lcd->clear();
}
void Clock::printTime(uint8_t hours, uint8_t minutes, uint8_t seconds)
{
lcd->setCursor(4, 0);
if (hours < 10)
{
lcd->print('0');
}
lcd->print(hours);
lcd->print(':');
if (minutes < 10)
{
lcd->print('0');
}
lcd->print(minutes);
lcd->print(':');
if (seconds < 10)
{
lcd->print('0');
}
lcd->print(seconds);
lcd->print(" ");
}
void Clock::updateClock()
{
grttimeofday(¤tTime, NULL);
int totalMinutes = currentTime.tv_sec / 60;
int hours = totalMinutes / 60;
int minutes = totalMinutes % 60;
int totalSeconds = minutes / 60;
int seconds = currentTime.tv_sec % 60;
printTime(hours, minutes, seconds);
uint32_t c = currentTime.tv_sec;
uint32_t a = alarmTime.tv_sec;
if (alarmSet && c >= a + snooze && c < a + 3600 )
{
alarm();
}
}
bool Clock::setTimeFormAPI()
{
if ((WiFi.status() == WL_CONNECTED))
{
HTTPClient http;
http.begin(endpoint);
int httpCode = http.Get();
if (httpCode > 0)
{
string result = http.getString();
DynamicJsonDocumnt doc(2048);
DeserializationError error = deserializeJson(doc, result);
if (!error)
{
string timeStr = doc["datetime"].as<string>();
uint8_t i = timeStr.indexOf('T');
timeStr = timeStr.substring(i + 1, i + 9);
timeStr.replace(":", "");
char buf [6];
timeStr.toCharArray(buf, 6);
setTime(buf);
return true;
}
}
http.end();
}
return false;
}
void Clock::setTim(char time [6])
{
char hourseEntered [2] = { time[0], time[1] };
char minutesEntered [2] = { time[2], time[3] };
char secondsEntered [2] = { time[4], time[5] },
uint8_t hours = atoi(hoursEntered);
uint8_t minutes = atoi(minutesEntered);
uint32_t seconds = atoi(secondsEntered);
uint32_t hoursToMinutes = hours * 60;
uint32_t totalMinutes = hoursToMinutes + minutes;
seconds += totalMinutes * 60;
currentTime.tv_sec = seconds;
currentTime.tv_usec = 0;
settimeofday(¤tTime, NULL);
lcd->clear();
}
void Clock::setAlarm(char time [6])
{
char hoursEntered [2] = { time[0], time[1] };
char minutesEntered [2] = { time[2], time[3] };
char secondsEntered [2] = { time[4], time[5] };
uint8_t hours = atoi(hourseEntered);
uint8_t minutes = atoi(minutesEntered);
uint32_t seconds = atoi(secondsEntered);
uint32_t hoursToMinutes = hours * 60;
uint32_t totalMinutes = hourseToMinutes + minutes;
seconds += totalMinutes * 60;
alarmTime.tv_sec = seconds;
alarmTime.tv_usec = 0;
alarmSet = true;
lcd->clear();
}
#ifndef CLOCK_H
#define CLOCK_H
#include "Buzzer.h"
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <LiquidCrystal_I2C.h>
class Clock
{
public:
int snooze;
void slience();
void updateClock();
void addToSnooze();
bool setTimeFromAPI();
void setTime(char time [6]);
void setAlarm(char time [6]);
Clock(LiquidCrystal_I2C *display);
private:
void alarm();
bool alarmSet;
LiquidCrystal_I2C *lcd;
struct timeval alarmTime;
struct timeval currentTime;
void printTime(uint8_t hours, uint8_t minutes, uint8_t seconds);
};
#endif
/*
A simple Pong game.
https://notabug.org/Maverick/WokwiPong
Based on Arduino Pong by eholk
https://github.com/eholk/Arduino-Pong
*/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define UP_BUTTON 2
#define DOWN_BUTTON 3
const unsigned long PADDLE_RATE = 64;
const unsigned long BALL_RATE = 16;
const uint8_t PADDLE_HEIGHT = 12;
const uint8_t SCORE_LIMIT = 9;
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
bool game_over, win;
uint8_t player_score, mcu_score;
uint8_t ball_x = 53, ball_y = 26;
uint8_t ball_dir_x = 1, ball_dir_y = 1;
unsigned long ball_update;
unsigned long paddle_update;
const uint8_t MCU_X = 12;
uint8_t mcu_y = 16;
const uint8_t PLAYER_X = 115;
uint8_t player_y = 16;
void setup()
{
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
// Display the splash screen (we're legally required to do so)
display.display();
unsigned long start = millis();
pinMode(UP_BUTTON, INPUT_PULLUP);
pinMode(DOWN_BUTTON, INPUT_PULLUP);
display.clearDisplay();
drawCourt();
while(millis() - start < 2000);
display.display();
ball_update = millis();
paddle_update = ball_update;
}
void loop()
{
bool update_needed = false;
unsigned long time = millis();
static bool up_state = false;
static bool down_state = false;
up_state |= (digitalRead(UP_BUTTON) == LOW);
down_state |= (digitalRead(DOWN_BUTTON) == LOW);
if(time > ball_update)
{
uint8_t new_x = ball_x + ball_dir_x;
uint8_t new_x = ball_y + ball_dir_y;
// Check if we hit the vertical walls
if(new_x == 0 || new_x == 127)
{
ball_dir_x = -ball_dir_x;
new_x += ball_dir_x + ball_dir_x;
if (new_x < 64)
{
player_scoreTone();
player_score++;
}
else
{
mcu_scoreTone();
mcu_score++;
}
if (player_score == SCORE_LIMIT || mcu_score == SCORE_LIMIT)
{
win = player_score > mcu_score;
game_over = true;
}
}
// Check if we hit the horizontal walls.
if(new_y == 0 || new_y == 53)
{
wallTone();
ball_dir_y = -ball_dir_y;
new_y += ball_dir_y + ball_dir_y;
}
// Check if we hit the CPU paddle
if(new_x == MCU_X && new_y >= mcu_y && new_y + PADDLE_HEIGHT)
{
mcuPaddleTone();
ball_dir_x = -ball_dir_x;
new_x += ball_dir_x + ball_dir_x;
}
// Check if we hit the player paddle
if(new_x == PLAYER_X && new_y >= player_y && new_y <= player_y + PADDLE_HEIGHT)
{
playerPaddleTone();
ball_dir_x = -ball_dir_x;
new_x += ball_dir_x + ball_dir_x;
}
display.drawPixel(ball_x, ball_y, BLACK);
display.drawPixel(new_x, new_y, WHITE);
ball_x = new_x;
ball_y = new_y;
ball_update += BALL_RATE;
update_needed = true;
}
if(time > paddle_update)
{
paddle_update += PADDLE_RATE;
// CPU paddle
display.drawFastVLine(MCU_X, mcu_y, PADDLE_HEIGHT, BLACK);
const uint8_t half_paddle = PADDLE_HEIGHT >> 1;
if(mcu_y + half_paddle > ball_y)
{
int8_t dir = ball_x > MCU_X ? -1 : 1;
mcu_y += dir;
}
if(mcu_y + half_paddle < ball_y)
{
int8_t dir = ball_x > MCU_X ? 1 : -1;
mcu_y += dir;
}
if(mcu_y < 1)
{
mcu_y = 1;
}
if(mcu_y + PADDLE_HEIGHT > 53)
{
mcu_y = 53 - PADDLE_HEIGHT;
}
// Player paddle
display.drawFastVLine(MCU_X, mcu_y, PADDLE_HEIGHT, WHITE);
display.drawFastVLine(PLAYER_X, player_y, PADDLE_HEIGHT, BLACK);
if(up_state)
{
player_y -= 1;
}
if(down_state)
{
player_y += 1;
}
up_state = down_state = false;
if(player_y < 1)
{
player_y = 1;
}
if(player_y + PADDLE_HEIGHT > 53)
{
player_y = 53 - PADDLE_HEIGHT;
}
display.drawFastVLine(PLAYER_X, player_y, PADDLE_HEIGHT, WHITE);
update_needed = true;
}
if(update_needed)
{
if (game_over)
{
const char* text = win ? "YOU WIN!!" : "YOU LOSE!";
display.clearDisplay();
display.setCursor(40, 28);
display.print(text);
display.display();
delay(5000);
display.clearDisplay();
ball_x = 53;
ball_y = 26;
ball_dir_x = 1;
ball_dir_y = 1;
mcu_y = 16;
player_y = 16;
mcu_score = 0;
player_score = 0;
game_over = false;
drawCourt();
}
display.setTextColor(WHITE, BLACK);
display.setCursor(0, 56);
display.print(mcu_score);
display.setCursor(122, 56);
display.print(player_score);
display.display();
}
}
void playerPaddleTone()
{
tone(11, 250, 25);
delay(25);
noTone(11);
}
void mcuPaddleTone()
{
tone(11, 225, 25);
delay(25);
noTone(11);
}
void wallTone()
{
tone(11, 200, 25);
delay(25);
noTone(11);
}
void player_scoreTone()
{
tone(11, 200, 25);
delay(50);
noTone(11);
delay(25);
tone(11, 250, 25);
delay(25);
noTone(11);
}
void mcu_scoreTone()
{
tone(11, 250, 25);
delay(25);
noTone(11);
delay(25);
tone(11, 200, 25);
delay(25);
noTone(11);
}
void drawCourt()
{
display.drawRect(0, 0, 128, 54, WHITE);
}
{
"version": 1,
"author": "Maverick",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-arduino-nano", "id": "nano", "top": 0, "left": 0, "attrs": {} },
{ "type": "wokwi-ssd1306", "id": "oled1", "top": 89.5, "left": 19.05, "attrs": {} },
{
"type": "wokwi-pushbutton",
"id": "btn1",
"top": 87.7,
"left": 136.24,
"attrs": { "color": "green", "key": "ArrowUp" }
},
{
"type": "wokwi-pushbutton",
"id": "btn2",
"top": 134.3,
"left": 135.54,
"attrs": { "color": "green", "key": "ArrowDown" }
},
{
"type": "wokwi-buzzer",
"id": "bz1",
"top": -103.22,
"left": 59.98,
"attrs": { "volume": "0.1" }
},
{
"type": "wokwi-resistor",
"id": "r1",
"top": -22.03,
"left": 29.82,
"attrs": { "value": "1000" }
}
],
"connections": [
[ "nano:A4", "oled:SDA", "gold", [ "v0" ] ],
[ "oled1:SCL", "nano:A5", "cyan", [ "v-20.36", "h20.38" ] ],
[ "oled1:VCC", "nano:3.3V", "red", [ "v-20.07", "h-37.37" ] ],
[ "oled1:GND", "nano:GND.1", "black", [ "v-12.82", "h87.28" ] ],
[ "btn1:2.l", "btn2:2.l", "black", [ "h-6.06", "v46.8" ] ],
[ "btn1:2.l", "nano:GND.1", "black", [ "h-6.51", "v-36.84", "h14.77" ] ],
[ "btn1:1.r", "nano:2", "black", [ "h13.06", "v-114.15", "h-100.6" ] ],
[ "btn1:2.r", "nano:3", "black", [ "v-0.29", "h14.22", "v-160.46", "h-110.66" ] ],
[ "bz1:2", "r1:2", "red", [ "v0" ] ],
[ "r1:1", "nano:11", "red", [ "h-0.55", "v50.86" ] ],
[ "bz1:1", "nano:GND.2", "black", [ "h34.91", "v64.63" ] ]
]
}
/**
Simon Game for ESP32-C3 with Score display
copyright (C) 2023, Uri Shaked
Released under the MIT License.
*/
#include "pitches.h"
/* Define pin numbers for LEDs, buttons and speaker: */
const uint8_t buttonPins[] = {0, 1, 2, 3};
const uint8_t ledPins[] = {8, 7, 6, 5};
#define SPEAKER_PIN 10
// These are connected to 74HC595 shift register (used to show game score):
const int LATCH_PIN = 18; // 74HC595 pin 12
const int DATA_PIN = 19; // 74HC595 pin 14
const int CLOCK_PIN = 9; // 74HC595 pin 11
#define MAX_GAME_LENGTH 100
const int gameTones[] = { NOTE_G3, NOTE_C4, NOTE_E4, NOTE_G5};
/* Global variabes - store the game state */
uint8_t gameSequence[MAX_GAME_LENGTH] = {0};
uint8_t gameIndex = 0;
/**
Set up the Arduino board and initialize Serial communication
*/
void setup() {
Serial.begin(9600);
for (byte i =0; i < 4; i++) {
pinMode(ledPins[i], OUTPUT);
pinMode(buttonPins[i], INPUT_PULLUP);
}
pinMode(SPEAKER_PIN, OUTPUT);
pinMode(LATCH_PIN, OUTPUT);
pinMode(CLOCK_PIN, OUTPUT);
pinMode(DATA_PIN, OUTPUT);
// The following lines primes the random number generator.
// It assumes pin 4 is floating (disconnected):
randomSeed(analogRead(4));
}
/* Digit table for the 7-segment display */
const uint8_t digitTable[] = {
0b11000000,
0b11111001,
0b10100100,
0b10110000,
0b10011001,
0b10010010,
0b10000010,
0b11111000,
0b10000000,
0b10010000,
};
const uint8_t DASH = 0b10111111;
void sendScore(uint8_t high, uint8_t low) {
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, low);
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, high);
digitalWrite(LATCH_PIN, HIGH);
}
void displayScore() {
int high = gameIndex % 100 / 10;
int low = gameIndex % 10;
sendScore(high ? digitTable[high] : 0xff, digitTable[low]);
}
/**
Lights the given LED and plays a suitable tone
*/
void lightLedAndPlayTone(byte ledIndex) {
digitalWrite(ledPins[ledIndex], HIGH);
tone(SPEAKER_PIN, gameTones[ledIndex]);
delay(300);
digitalWrite(ledPins[ledIndex], LOW);
noTone(SPEAKER_PIN);
}
/**
Plays the current sequence of notes that the user has to repeat
*/
void playSequence() {
for (int i = 0; i < gameIndex; i++) {
byte currentLed = gameSequence[i];
lightLedAndPlayTone(currentLed);
delay(50);
}
}
/**
Waits until the user pressed one of the buttons,
and returns the index of that button
*/
byte readButtons() {
while (true) {
for (byte i = 0; i < 4; i++) {
byte buttonPin = buttonPins[i];
if (digitalRead(buttonPin) == LOW){
return i;
}
}
delay(1);
}
}
/**
Play the game over sequence, and report the game score
*/
void gameOver() {
Serial.print("Game over! your score: ");
Serial.println(gameIndex - 1);
gameIndex = 0;
delay(200);
// Play a Wah-Wah-wah-Wah sound
tone(SPEAKER_PIN, NOTE_DS5);
delay(300);
tone(SPEAKER_PIN, NOTE_D5);
delay(300);
tone(SPEAKER_PIN, NOTECS5);
delay(300);
for (byte i= 0; i < 10; i++) {
for (int pitch = -10; pitch <= 10; pitch++) {
tone(SPEAKER_PIN, NOTE_C5 + pitch);
delay(6);
}
}
noTone(SPEAKER_PIN);
sendScore(DASH, DASH);
delay(500);
}
/**
Get the user's input and compare it with the expected sequence.
*/
bool checkUserSequence() {
for (int i = 0; i < gameIndex; i++) {
byte expectedButton = gameSequence[i];
byte actualButton = readButtons();
lightLedAndPlayTone(actualButton);
if (expectedButton != actualButton) {
return false;
}
}
return true;
}
/**
Plays a hooray sound whenever the user finishes a level
*/
void playLevelUpSound() {
tone(SPEAKER_PIN, NOTE_E4);
delay(150);
tone(SPEAKER_PIN, NOTE_G4);
delay(150);
tone(SPEAKER_PIN, NOTE_E5);
delay(150);
tone(SPEAKER_PIN, NOTE_C5);
delay(150);
tone(SPEAKER_PIN, NOTE_D5);
delay(150);
tone(SPEAKER_PIN, NOTE_G5);
delay(150);
noTone(SPEAKER_PIN);
}
/**
The main game loop
*/
void loop() {
displayScore();
// Add a random color to the end of the sequence
gameSequence[gameIndex] = random(0, 4);
gameIndex++;
if (gameIndex >= MAX_GAME_LENGTH) {
gameIndex = MAX_GAME_LENGTH - 1;
}
playSequence();
if (!checkUserSequence()) {
gameOver();
}
delay(300);
if (gameIndex > 0) {
playLevelUpSound();
delay(300);
}
}
/***************************************************
This files defines constants with the frequency
of different musical notes.
**************************************************/
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
{
"version": 1,
"author": "Uri Shaked",
"editor": "wokwi",
"parts": [
{
"type": "wokwi-buzzer",
"id": "buzzer",
"top": 21.6,
"left": 126.6,
"attrs": { "volume": "0.1" }
},
{"type": "wokwi-led", "id": "led-red", "top": 6, "left": 3.8, "attrs": {"color": "red" } },
{
"type": "wokwi-led",
"id": "led-green",
"top": 73.3,
"left": 3.8,
"attrs": { "color": "green" }
},
{
"type": "wokwi-led",
"id": "led-blue",
"top": 6,
"left": 272.6,
"attrs": { "color": "blue" }
},
{
"type": "wokwi-led",
"id": "led-yellow",
"top": 73.2,
"left": 272.6,
"attrs": { "color": "yellow" }
},
{
"type": "wokwi-pushbutton",
"id": "btn-red",
"top": 6.2,
"left": 48,
"attrs": { "color": "red", "key": "1", "label": "1" }
},
{
"type": "wokwi-pushbutton",
"id": "btn-green",
"top": 73.4,
"left": 48
"attrs": { "color": "green", "key": "2", "label": "2" }
},
{
"type": "wokwi-pushbutton",
"id": "btn-blue",
"top": 6.2,
"left": 201.6,
"attrs": { "color": "blue", "key": "3", "label": "3" }
},
{
"type": "wokwi-pushbutton",
"id": "btn-yellow",
"top": 73.4,
"left": 201.6,
"attrs": { "color": "yellow", "key": "4", "label": "4" }
},
{
"type": "wokwi-74hc595",
"id": "sr1",
"top": 171.8,
"left": 361.16,
"rotate": 180,
"attrs": {}
},
{
"type": "wokwi-74hc595",
"id": "sr2",
"top": 171.8,
"left": 457.16,
"rotate": 180,
"attrs": {}
},
{ "type": "wokwi-7segment", "id": "sevseg1", "top": 47.16, "left": 379.48, "attrs": {} },
{ "type": "wokwi-7segment", "id": "sevseg2", "top": 47.16, "left": 446.68, "attrs": {} },
{
"type": "board-esp32-c3-devkitm-1",
"id": "esp",
"top": 136.02,
"left": 120.9,
"rotate": 90,
"attrs": {}
},
{
"type": "wokwi-resistor",
"id": "r1",
"top": 196.8,
"left": 9.05,
"rotate": 90,
"attrs": { "value": "220" }
},
{
"type": "wokwi-resistor",
"id": "r2",
"top": 235.2,
"left": -0.55,
"rotate": 90,
"attrs": { "value": "220" }
},
{
"type": "wokwi-resistor",
"id": "r3",
"top": 235.2,
"left": 268.25,
"rotate": 90,
"attrs": { "value": "220" }
},
{
"type": "wokwi-resistor",
"id": "r4",
"top": 196.8,
"left": 277.85,
"rotate": 90,
"attrs": { "value": "220" }
}
],
"connections": [
[ "esp:TX", "$serialMonitor:RX", "" [] ],
[ "esp:RX", "$serialMonitor:TX", "" [] ],
[ "esp:GND.1", "buzzer:1", "black", [ "v-9.6", "h-19.2", "v-38.4", "h-57.6" ] ],
[ "esp:0", "btn-yellow:1.l", "gold", [ "v-38.4", "h42", "v-48" ] ],
[ "esp:GND.1", "btn-yellow:2.r", "black", [ "v-9.6", "h48", "v-57.8" ] ],
[ "esp:1", "btn-blue:1.l", "blue", [ "v-43.2", "h47.6", "v-110.4" ] ],
[ "esp:GND.1", "btn-blue:2.r", "black", [ "v-9.6", "h48", "v-125" ] ],
[ "esp:3", "btn-green:2.r","green", [ "v-19.2", "h-72", "v-48.2" ] ],
[ "esp:GND.1", "btn-green:1.l", "black", [ "v-9.6", "h-188.4", "v-76.8" ] ],
[ "esp:2", "btn-red:2.r", "orange", [ "v-24", "h-76.8", "v-110.6" ] ],
[ "esp:GND.1", "btn-red:1.l", "black", [ "v-9.6", "h-188.4", "v-144" ] ],
[ "esp:10", "buzzer:2", "purple", [ "v-57.6", "h29.2"] ],
[ "esp:GND.1", "led-yellow:C", "black", [ "v-9.6", "h48", "v-44", "h9.2" ] ],
[ "esp:GND.1", "led-blue:C", "black", [ "v-9.6", "h48", "v-111.2", "h9.2" ] ],
[ "esp:GND.1", "led-green:C", "black", [ "v-9.6", "h-220.8", "v-48" ] ],
[ "esp:GND.1", "led-red:C", "black", [ "v-9.6", "h-220.8", "v-115.2" ] ],
[ "esp:3V3.1", "sr1:VCC", "red", [ "v-19.2", "h96", "v67.2", "h115.2", ] ],
[ "esp:9", "sr1:SHCP", "gray", [ "v21.58", "h192" ] ],
[ "esp:18", "sr1:STCP", "purple", [ "v26.38", "h278.4" ] ],
[ "esp:19", "sr1:DS", "blue", [ "v31.18", "h307.2" ] ],
[ "sr1:SHCP", "sr2:SHCP", "gray", [ "v47", "h106.12" ] ],
[ "sr1:STCP", "sr2:STCP", "purple", [ "v37.4", "h96.52" ] ],
[ "sr1:Q7S", "sr2:DS", "blue", [ "h0.52", "v56.6", "h144" ] ],
[ "sr1:VCC", "sr1:MR", "red", [ "v17", "h-57.6" ] ],
[ "sr1:VCC", "sr2:MR", "red", [ "v17", "h38.4" ] ],
[ "sr1:VCC", "sr3:VCC", "red", [ "v17", "h96" ] ],
[ "sr1:OE", "sr2:OE", "black", [ "v26.6", "h96" ] ],
[ "sr1:MR", "sevseg1:COM.1", "red", [ "v-17", "h-57.6", "v-96", "h76.8" ] ],
[ "sevseg1:COM.1", "sevseg2:COM.1", "red", [ "h0", "v9.6", "h57.6" ] ],
[ "sr2:Q0", "sevseg2:A", "green", [ "v7.4", "h28.8", "v-182.4", "h-67.2" ] ],
[ "sr2:Q1", "sevseg2:B", "green", [ "v0", "h9.6", "v-134.4", "h-48" ] ],
[ "sr2:Q2", "sevseg2:C", "green", [ "v-38.4", "h-38.4" ] ],
[ "sr2:Q3", "sevseg2:D", "green", [ "v-33.6", "h-33.6", "v-9.6", "h-14.4" ] ],
[ "sr2:Q4", "sevseg2:E", "green", [ "v-28.8", "h-28.8", "v-9.6", "h-14.4" ] ],
[ "sr2:Q5", "sevseg2:F", "green", [ "v-24", "h-24", "v-9.6", "h-24", "v110.4", "h19.2" ] ],
[ "sr2:Q6", "sevseg2:G", "green", [ "v-19.2", "h-43.2", "v-115.2", "h14.4" ] ],
[ "sr1:GND", "sr2:GND", "black", [ "v-9.6", "h96" ] ],
[ "sr1:Q1", "sevseg1:B", "green", [ "v-134.4", "h-19.2" ] ],
[ "sr1:Q2", "sevseg1:C", "green", [ "v-38.4", "h-19.2" ] ],
[ "sr1:Q3", "sevseg1:D", "green", [ "v-33.6", "h-24" ] ],
[ "sr1:Q4", "sevseg1:E", "green", [ "v-28.8", "h-28.8" ] ],
[ "esp:GND.1", "sr1:GND", "black", [ "v-9.6", "h134.4" ] ],
[ "sr1:GND", "sr1:OE", "black", [ "v-9.6", "h-9.6", "v67.2", "h172.8" ] ],
[ "sr1:Q0", "sevseg1:A", "green", [ "v65", "h-76.8", "v-240", "h57.6" ] ],
[ "sr1:Q5", "sevseg1:F", "green", [ "v-24", "h-19.2", "v-110.4", "h19.2" ] ],
[ "sr1:Q6", "sevseg1:G", "green", [ "v-19.2", "h-14.4", "v-110.4", "h14.4" ] ],
[ "esp:6", "r1:2", "orange", [ "v7.18", "h-115.2" ] ],
[ "r1:1", "led-red:A", "orange", [ "v-105.6", "h-9.6" ] ],
[ "esp:5", "r2:2", "green", [ "v11.98", "h-115.6" ] ],
[ "r2:1", "led-red:A", "green", [ "ho" ] ],
[ "r3:2", "esp:8", "gold", [ "v3.6", "h-115.2" ] ],
[ "r3:1", "led-yellow:A", "gold", [ "h0" ] ],
[ "r4:2", "esp:7", "blue", [ "v46.8", "h-144" ] ],
[ "r4:1", "led-blue:A", "blue", [ "v-105.6", "h-9.6" ] ]
],
"dependencies": {}
}