Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
Introduction
Hi, Everyone.I introduce my mbed project. I've making Real-time bus arrival alarm . This device project for busy people in the morning. Perhaps, you could be more freely checking bus arrival without mobile phone by this device.
* This project made by korean. If you live in foreign country, you may need to be modified for Bus information system in yours.
Step 1: Concept
Step 2: Parts
For this project, you'll need next things.
-
WIZnet WIZwiki-W7500 IoT Platform board
- W7500 MCU embedded, 32-bit ARM® Cortex™-M0 core with Hardwired TCP/IP
- ARM mbed official platform board
- for more details, refer to the http://wizwiki.net/wiki/doku.php?id=products:wizwi...
- Seeed Studio Grove Devices
- Grove OLED Display 96x96
- Grove 4-Digit Display
- Grove Buzzer
- Grove Base Shield v2 and Connectors
- for more details, refer to the http://www.seeedstudio.com/wiki/Grove_System
- A Computer connecting to Internet
- ARM mbed platform provided Web compiler (IDE)
Step 3: Hardware Configuration
Step 4: Used Libraries
This project based on ARM mbed platform (with libraries at mbed)
- HTTP client
- NTP client
- Grove OLED display 96x96
- Grove 4-digit display
Step 5: Get the Bus Arrival Informations
- Note: These steps for using GBIS (Gyeonggi Bus Information System) in Korea.
Following next steps.
- Check and get the Bus number and station(bus stop) number you need.
- Get the Bus base information using openAPI (refer to below URL example)
- Lookup the matched route ID and station ID in route / station database using bus number and station number.
- Get the Bus arrival information using openAPI (refer to below URL example)
- Done
Step #2 URL Example: Bus base information request (key)
http://openapi.gbis.go.kr/ws/rest/baseinfoservice?serviceKey=test
Step #4 URL Example: Bus arrival information request (key, routeID, stationID)
Step 6: Import the Project on mbed Web Compiler
Visit follow link; mbed project repository
https://developer.mbed.org/users/hkjung/code/Real-time_Bus_Arrival_Alarm/
Press 'Import this Program' button in Repository toolbox
- Note: MAC address is the unique ID for your network device. It must be modified as your MAC.
- Link: Handbook - mbed Compiler Getting Started
- https://developer.mbed.org/handbook/mbed-Compiler-Getting-Started
Step 7: Build and Run
Writing firmware into WIZwiki-W7500 and RUN!
- Link: How to write the firmware into WIZwiki-W7500
- Please refer to the 'Using the CMSIS-DAP (Drag and Drop)' - very easy!
- http://wizwiki.net/wiki/doku.php?id=products:wizwiki_w7500:start_getting_started:write_firmware
Enjoy it!
Real-time Bus Arrival Alarm: main.cpp
C/C++* Note: whole project located in mbed repository - https://developer.mbed.org/users/hkjung/code/Real-time_Bus_Arrival_Alarm/
#include "mbed.h"
#include "EthernetInterface.h"
#include "HTTPClient.h" // HTTP Client library
#include "NTPClient.h" // NTP Client library (Network Time Protocol)
#include "DigitDisplay.h" // Seeed Grove: 4-digit Display
#include "SeeedGrayOLED.h" // Seeed Grove: OLED Display 0.96" 96x96
Serial pc(USBTX, USBRX);
PwmOut Buzzer(D6);
DigitDisplay display(D0, D1); // 4-Digit Display connected to UART Grove connector
SeeedGrayOLED SeeedGrayOled(D14, D15);
DigitalOut myled(LED1);
Ticker tick;
////////////////////////////////////////////////////////////////
// Defines
////////////////////////////////////////////////////////////////
/* User adjustable defines */
////////////////////////////////////////////////////////////////
/* Debug Message Enable */
#define _DEBUG_BUS_ARRIVAL_ALARM_ 0
/* Number of Displayed Bus Info */
#define MAX_BUS_INFO 3 // The maximum bus information request can be up to Three (3)
/* Display mode */
#define DISPLAY_MODE_CHANGE_CNT_SEC 10 // The OLED display holding time(sec) for each bus information displayed
#define BUS_NUM_BLINK_ENABLE 1 // blink the 4-digit display when displayed bus numbers
/* Alarm Sound Enabled and Time */
#define ALARM_SOUND_ENABLE 1
#define SOUND_START_HOUR 6
#define SOUND_START_MIN 15
#define SOUND_END_HOUR 07
#define SOUND_END_MIN 00
/* HTTP client */
//#define MAX_HTTPC_RETRY_CNT 2 // not used
////////////////////////////////////////////////////////////////
/* Buzzer */
#define VOLUME 0.2 // 0.02
#define BPM 100.0
/* Display mode define */
#define DISPLAY_TIME_MODE 0 // do not change!
/* Bus and Station (Busstop) info for GBIS openAPI */
#define DEFAULT_STATION_NUM 38270 //(Gwangju -> Seoul)
#define DEFAULT_STATION_ID 234000302
// for test
//#define DEFAULT_STATION_NUM 38269 //(Seoul -> Gwangju)
//#define DEFAULT_STATION_ID 234000294
typedef struct
{
uint8_t * busNum; // Bus number, This value should be input at initialize stage
uint16_t stationNum; // Station number, notused, This value should be input at initialize stage
uint32_t routeId; // Bus route id for openAPI querying (openapi.gbis.go.kr) // This value should be input at initialize stage
uint32_t stationId; // Bus station id for openAPI querying (openapi.gbis.go.kr) // This value should be input at initialize stage
uint8_t resultCode; // 0; success, 4; bus info none
uint8_t predictTime1; // 1st bus arrival predict time ('1' means the bus gone)
uint8_t predictTime2; // 2st bus arrival predict time ('1' means the none of next bus info)
uint8_t remainSeatCnt1; // 1st bus remain seat count
uint8_t remainSeatCnt2; // 2st bus remain seat count
}BUSINFO;
////////////////////////////////////////////////////////////////
// Function declaration
////////////////////////////////////////////////////////////////
void BuzzerSound(void); // Buzzer
void Display_BusNumber(uint8_t * busnum); // 4-digit display
uint8_t get_businfo(BUSINFO * bus); // Get Bus information (HTTP client)
// OLED display
void Draw_OLED_init(void);
void Draw_OLED_default(void);
void Draw_OLED_busInfo(uint8_t * busnum, uint8_t seats);
void Draw_OLED_arrivalMin(uint8_t min);
void Draw_OLED_nextMin(uint8_t nextmin);
void Draw_OLED_busList(void);
// for ticker
void beat();
////////////////////////////////////////////////////////////////
// Global variable declaration
////////////////////////////////////////////////////////////////
BUSINFO businfo[MAX_BUS_INFO];
uint8_t flag_display_mode[MAX_BUS_INFO+1] = {0, };
uint8_t display_mode = 0;
uint8_t buzzer_sound_enable = 0;
time_t beat_cTime;
struct tm *beat_localtime;
uint8_t mac[6] = {0x00,0x08,0xDC,0x01,0x02,0x03}; // MAC address, It must be modified as users MAC address
int main()
{
pc.baud(115200);
EthernetInterface ethernet;
uint8_t i;
////////////////////////////////////////////////////////////////
// Realtime Bus Information: Initialization
////////////////////////////////////////////////////////////////
/* Bus number and route ID */
uint8_t busnum_1117[4] = {1, 1, 1, 7};
uint32_t busnum_1117_routeId = 234000069;
uint8_t busnum_1113[4] = {1, 1, 1, 3};
uint32_t busnum_1113_routeId = 234000042;
uint8_t busnum_1005[4] = {1, 0, 0, 5};
uint32_t busnum_1005_routeId = 234000065;
// Bus info structure initialize
businfo[0].busNum = busnum_1117;
businfo[0].stationNum = DEFAULT_STATION_NUM;
businfo[0].routeId = busnum_1117_routeId;
businfo[0].stationId = DEFAULT_STATION_ID;
businfo[1].busNum = busnum_1113;
businfo[1].stationNum = DEFAULT_STATION_NUM;
businfo[1].routeId = busnum_1113_routeId;
businfo[1].stationId = DEFAULT_STATION_ID;
businfo[2].busNum = busnum_1005;
businfo[2].stationNum = DEFAULT_STATION_NUM;
businfo[2].routeId = busnum_1005_routeId;
businfo[2].stationId = DEFAULT_STATION_ID;
// OLED display initialize
SeeedGrayOled.init(); // Initialize SEEED OLED display
SeeedGrayOled.clearDisplay(); // Clear Display
SeeedGrayOled.setNormalDisplay(); // Set Normal Display Mode
// OLED display initial draw
Draw_OLED_default(); //Draw_OLED_init();
printf("\r\n==========================================\r\n");
printf(" Real-time Bus Arrival Alarm\r\n");
printf("==========================================\r\n");
printf(" Buzzer Sound START Time: %d:%.2d\r\n", SOUND_START_HOUR, SOUND_START_MIN);
printf(" Buzzer Sound END Time : %d:%.2d\r\n", SOUND_END_HOUR, SOUND_END_MIN);
printf("==========================================\r\n");
// Ethernet initialize
int ret = ethernet.init(mac);
printf("\r\nWIZwiki-W7500 Networking Started\r\n");
wait(1); // 1 second for stable state
if (!ret) {
printf("Initialized, MAC: %s\r\n", ethernet.getMACAddress());
ret = ethernet.connect();
if (!ret) {
printf("IP: %s, MASK: %s, GW: %s\r\n",
ethernet.getIPAddress(), ethernet.getNetworkMask(), ethernet.getGateway());
} else {
printf("Error ethernet.connect() - ret = %d\r\n", ret);
exit(0);
}
} else {
printf("Error ethernet.init() - ret = %d\r\n", ret);
exit(0);
}
// NTP initialize
NTPClient ntp;
printf("\r\nTrying to update time...\r\n");
if (ntp.setTime("211.233.40.78") == 0)
{
printf("Set time successfully\r\n");
time_t ctTime;
ctTime = time(NULL);
ctTime += 32400; // GMT+9/Seoul
printf("Time is set to (GMT+9): %s\r\n", ctime(&ctTime));
}
else
{
printf("Error\r\n");
}
// 4-Digit display initialize
display.write(0, 0);
display.write(1, 0);
display.write(2, 0);
display.write(3, 0);
display.setColon(true);
tick.attach(&beat, 0.5);
// Initial flag setting for get the bus info
flag_display_mode[DISPLAY_TIME_MODE] = 1;
printf(">> Initialize Done\r\n");
// Main routine
while(1) {
if(display_mode == DISPLAY_TIME_MODE) // Display: Time mode
{
if(flag_display_mode[display_mode])
{
Draw_OLED_default();
flag_display_mode[display_mode] = 0;
// Get the buses info: Bus arrival time preparation (beforehand)
for(i = 0; i < MAX_BUS_INFO; i++)
{
get_businfo(&businfo[i]);
#if (_DEBUG_BUS_ARRIVAL_ALARM_) //Debug message
printf("Businfo #%d\r\n", i);
printf("bus.resultCode = %c\r\n", businfo[i].resultCode);
printf("1st Bus arrive after %d min\r\n", businfo[i].predictTime1);
printf("1st Bus remain seats %d\r\n", businfo[i].remainSeatCnt1);
printf("2nd Bus arrive after %d min\r\n", businfo[i].predictTime2);
printf("2nd Bus remain seats %d\r\n\r\n", businfo[i].remainSeatCnt2);
#endif
}
}
}
else // Display: Bus info mode
{
i = display_mode - 1;
if(flag_display_mode[display_mode])
{
Draw_OLED_busInfo(businfo[i].busNum, businfo[i].remainSeatCnt1);
Draw_OLED_arrivalMin(businfo[i].predictTime1);
if(businfo[i].predictTime2 == 1)
{
Draw_OLED_nextMin(0);
}
else
{
Draw_OLED_nextMin(businfo[i].predictTime2);
}
// Buzzer sound!
// Each case means the displayed time(Remaining time until the bus arrival, minute) to ringing the buzzer
switch(businfo[i].predictTime1)
{
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
BuzzerSound();
break;
default:
break;
}
flag_display_mode[display_mode] = 0;
}
}
}
}
////////////////////////////////////////////////////////////////
// Member function of Ticker interface (attaching to a ticker)
////////////////////////////////////////////////////////////////
void beat()
{
static uint8_t colon = 0;
static uint8_t myled_blink = 1;
static uint8_t display_mode_change_cnt = 0; // initial count value; 5 sec reduced
// Get current local time info
beat_cTime = time(NULL);
beat_cTime += 32400; // GMT+9/Seoul
beat_localtime = localtime(&beat_cTime);
// Display Mode change handler (Time / Bus mode)
display_mode_change_cnt++; // ++ every 0.5sec
if((display_mode_change_cnt/2) >= DISPLAY_MODE_CHANGE_CNT_SEC)
{
display_mode++;
if(display_mode > MAX_BUS_INFO)
{
display_mode = DISPLAY_TIME_MODE; // 0
}
// Skip: (resultCode == 4) means 'Bus arrival info does not appear'
while((display_mode != DISPLAY_TIME_MODE) && (businfo[display_mode-1].resultCode == 4))
{
display_mode++;
if(display_mode > MAX_BUS_INFO)
{
display_mode = DISPLAY_TIME_MODE; // 0
}
}
flag_display_mode[display_mode] = 1;
display_mode_change_cnt = 0;
}
// 4-Digit Display handler
if(display_mode == DISPLAY_TIME_MODE) // Time mode
{
display.on();
display.setColon(colon);
if (colon) {
display.write(0, beat_localtime->tm_hour / 10);
display.write(1, beat_localtime->tm_hour % 10);
display.write(2, beat_localtime->tm_min / 10);
display.write(3, beat_localtime->tm_min % 10);
}
//colon = 1 - colon; // moved below
}
else // Bus info mode
{
#if (BUS_NUM_BLINK_ENABLE)
if(colon)
{
Display_BusNumber(businfo[display_mode-1].busNum);
}
else
{
Display_BusNumber(NULL);
}
#else
Display_BusNumber(businfo[display_mode-1].busNum);
#endif
}
// Buzzer sound enable handler
buzzer_sound_enable = 0;
#if (ALARM_SOUND_ENABLE)
if(((beat_localtime->tm_hour == SOUND_START_HOUR) && (beat_localtime->tm_min >= SOUND_START_MIN)) || (beat_localtime->tm_hour > SOUND_START_HOUR))
{
if((beat_localtime->tm_hour < SOUND_END_HOUR) || ((beat_localtime->tm_hour == SOUND_END_HOUR) && (beat_localtime->tm_min < SOUND_END_MIN)))
{
buzzer_sound_enable = 1;
}
}
#endif
// LED blink; Device working indicator
myled_blink ^= 1;
myled = myled_blink ;
// Invert every 0.5sec
colon = 1 - colon;
}
////////////////////////////////////////////////////////////////
// Get Bus Information (HTTP client) Functions
////////////////////////////////////////////////////////////////
uint8_t get_businfo(BUSINFO * bus)
{
uint8_t ret = 0;
char str[2048] = {0, };
char get_req[512] = {0, };
char predictTime1[3], predictTime2[3];
char remainSeatCnt1[3], remainSeatCnt2[3];
char *CurrentAddr = 0;
//uint8_t retry_cnt = 0; // Unimplemented, MAX_HTTPC_RETRY_CNT
HTTPClient httpc;
sprintf(get_req, "http://openapi.gbis.go.kr/ws/rest/busarrivalservice?serviceKey=test&routeId=%ld&stationId=%ld", bus->routeId, bus->stationId);
httpc.get(get_req, str, sizeof(str), 1000);
CurrentAddr = strstr(str,"<resultCode>");
bus->resultCode = *(CurrentAddr+12);
if(bus->resultCode == '0')
{
CurrentAddr = strstr(str,"<predictTime1>");
if((*(CurrentAddr+15)) == '<')
{
predictTime1[0] = *(CurrentAddr+14);
predictTime1[1] = 0;
predictTime1[2] = 0;
}
else
{
predictTime1[0] = *(CurrentAddr+14);
predictTime1[1] = *(CurrentAddr+15);
predictTime1[2] = 0;
}
bus->predictTime1 = (uint8_t)atoi(predictTime1);
CurrentAddr = strstr(str,"<predictTime2>");
if((*(CurrentAddr+15)) == '<')
{
predictTime2[0] = *(CurrentAddr+14);
predictTime2[1] = 0;
predictTime2[2] = 0;
}
else
{
predictTime2[0] = *(CurrentAddr+14);
predictTime2[1] = *(CurrentAddr+15);
predictTime2[2] = 0;
}
bus->predictTime2 = (uint8_t)atoi(predictTime2);
CurrentAddr = strstr(str,"<remainSeatCnt1>");
if((*(CurrentAddr+17)) == '<')
{
remainSeatCnt1[0] = *(CurrentAddr+16);
remainSeatCnt1[1] = 0;
remainSeatCnt1[2] = 0;
}
else
{
remainSeatCnt1[0] = *(CurrentAddr+16);
remainSeatCnt1[1] = *(CurrentAddr+17);
remainSeatCnt1[2] = 0;
}
bus->remainSeatCnt1 = (uint8_t)atoi(remainSeatCnt1);
if(bus->predictTime2 > 1) // (predictTime2 == 1) => The next bus information is not confirmed.
{
CurrentAddr = strstr(str,"<remainSeatCnt2>");
if((*(CurrentAddr+17)) == '<')
{
remainSeatCnt2[0] = *(CurrentAddr+16);
remainSeatCnt2[1] = 0;
remainSeatCnt2[2] = 0;
}
else
{
remainSeatCnt2[0] = *(CurrentAddr+16);
remainSeatCnt2[1] = *(CurrentAddr+17);
remainSeatCnt2[2] = 0;
}
bus->remainSeatCnt2 = (uint8_t)atoi(remainSeatCnt2);
}
ret = 1;
}
return ret;
}
////////////////////////////////////////////////////////////////
// Piezo Buzzer Functions
////////////////////////////////////////////////////////////////
void playNote(float frequency, float duration, float volume)
{
Buzzer.period(1.0/(double)frequency);
Buzzer = ((double)volume/2.0);
wait(duration);
Buzzer = 0.0;
}
void BuzzerSound(void)
{
// Calculate duration of a quarter note from bpm
float beat_duration = 60.0 / BPM;
if(buzzer_sound_enable)
{
//playNote(329.628, (0.75 * (double)beat_duration), VOLUME);
//playNote(261.626, (0.75 * (double)beat_duration), VOLUME);
playNote(529.628, (0.50 * (double)beat_duration), VOLUME);
playNote(301.626, (0.50 * (double)beat_duration), VOLUME);
}
}
////////////////////////////////////////////////////////////////
// 4-Digit Display Functions
////////////////////////////////////////////////////////////////
void Display_BusNumber(uint8_t * busnum)
{
display.setColon(false);
if(busnum != NULL)
{
display.on();
display.write(0, busnum[0]);
display.write(1, busnum[1]);
display.write(2, busnum[2]);
display.write(3, busnum[3]);
}
else
{
display.off();
}
}
////////////////////////////////////////////////////////////////
// OLED Display Functions
////////////////////////////////////////////////////////////////
void Draw_OLED_init(void)
{
uint8_t empty_busnum[4] = {0, 0, 0, 0};
Draw_OLED_busInfo(empty_busnum, 0);
Draw_OLED_nextMin(0);
}
void Draw_OLED_default(void)
{
SeeedGrayOled.setTextXY(0, 1);
SeeedGrayOled.putString("Bus NearBy ");
SeeedGrayOled.setTextXY(1, 1);
SeeedGrayOled.putString("========== ");
Draw_OLED_arrivalMin('b');
SeeedGrayOled.setTextXY(11, 0);
SeeedGrayOled.putString("WIZnet::Eric");
}
void Draw_OLED_busList(void)
{
uint8_t i;
char buf[15] = {0, };
SeeedGrayOled.setTextXY(0, 1);
SeeedGrayOled.putString(" ");
SeeedGrayOled.setTextXY(1, 1);
SeeedGrayOled.putString("Bus List:");
Draw_OLED_arrivalMin('t');
for(i = 0; i < MAX_BUS_INFO; i++)
{
SeeedGrayOled.setTextXY(3+i, 2);
sprintf(buf, "- %.1d%.1d%.1d%.1d", businfo[i].busNum[0], businfo[i].busNum[1], businfo[i].busNum[2], businfo[i].busNum[3]);
SeeedGrayOled.putString(buf);
}
SeeedGrayOled.setTextXY(11, 1);
SeeedGrayOled.putString(" ");
}
void Draw_OLED_busInfo(uint8_t * busnum, uint8_t seats)
{
char buf[15] = {0, };
sprintf(buf, "Bus %.1d%.1d%.1d%.1d ", busnum[0], busnum[1], busnum[2], busnum[3]);
SeeedGrayOled.setTextXY(0, 1);
SeeedGrayOled.putString(buf);
sprintf(buf, "Seats %.2d ", seats);
SeeedGrayOled.setTextXY(1, 1);
SeeedGrayOled.putString(buf);
}
void Draw_OLED_nextMin(uint8_t nextmin)
{
char buf[15] = {0, };
if(nextmin == 0)
{
sprintf(buf, "Next: -- min");
}
else
{
sprintf(buf, "Next: %.2d min", nextmin);
}
SeeedGrayOled.setTextXY(11, 0);
SeeedGrayOled.putString(buf);
}
void Draw_OLED_arrivalMin(uint8_t min)
{
switch(min)
{
case 't':
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ");
break;
case 'b':
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~~~~~~~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ~~~ ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~~~~~~~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~~ ~~ ");
break;
case 0:
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~~~ ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~ ~ ~ ~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ~ ~ ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ~ ~ ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~~~~ ~~~~ ");
break;
case 1:
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~~~~~~~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" Gone! ");
break;
case 2:
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~~~~ ");
break;
case 3:
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~~~~ ");
break;
case 4:
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~ ");
break;
case 5:
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~~~~ ");
break;
case 6:
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~~~~ ");
break;
case 7:
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~ ");
break;
case 8:
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~~~~ ");
break;
case 9:
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~~~~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~~~~ ");
break;
case 10:
case 11: // 10
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~ ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~ ~~~~ ");
break;
case 12:
case 13:
case 14: // 12
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~ ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~ ~~~~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~ ~~~~ ");
break;
case 15:
case 16: // 15
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~ ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~ ~~~~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~ ~~~~ ");
break;
case 17:
case 18: // 17
case 19: // 17
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~ ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~ ~ ");
break;
case 20: // 20
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~~~ ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~~~~ ~ ~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~~~~ ~~~~ ");
break;
default: // 20
SeeedGrayOled.setTextXY(3, 0);
SeeedGrayOled.putString(" ~~~~ ~~~~ ");
SeeedGrayOled.setTextXY(4, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(5, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(6, 0);
SeeedGrayOled.putString(" ~~~~ ~ ~ ");
SeeedGrayOled.setTextXY(7, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(8, 0);
SeeedGrayOled.putString(" ~ ~ ~ ");
SeeedGrayOled.setTextXY(9, 0);
SeeedGrayOled.putString(" ~~~~ ~~~~ ~");
break;
}
}
Comments