├── .gitattributes ├── Crypto_Currency_-_ePaper ├── cryptos.h ├── coingecko-api.h └── Crypto_Currency_-_ePaper.ino └── Crypto_Currency_-_Serial_Monitor ├── cryptos.h ├── Crypto_Currency_-_Serial_Monitor.ino └── coingecko-api.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Crypto_Currency_-_ePaper/cryptos.h: -------------------------------------------------------------------------------- 1 | struct Price { 2 | double inr; 3 | String btc; 4 | String eth; 5 | }; 6 | 7 | struct Crypto 8 | { 9 | String apiName; 10 | String symbol; 11 | Price price; 12 | double dayChange; 13 | double weekChange; 14 | }; 15 | 16 | // ---------------------------- 17 | // Coin id list - adjust it to meet your interests 18 | // 19 | // Put your cryptocurrencies in the array below. 20 | // Get id of your coin here: https://api.coingecko.com/api/v3/coins/list?include_platform=false 21 | // ---------------------------- 22 | 23 | Crypto cryptos[] = { 24 | {"bitcoin"}, 25 | {"ethereum"}, 26 | {"dogecoin"}, 27 | {"tether"}, 28 | }; 29 | 30 | int cryptosCount = (sizeof(cryptos) / sizeof(cryptos[0])); 31 | -------------------------------------------------------------------------------- /Crypto_Currency_-_Serial_Monitor/cryptos.h: -------------------------------------------------------------------------------- 1 | struct Price { 2 | double inr; 3 | String btc; 4 | String eth; 5 | }; 6 | 7 | struct Crypto 8 | { 9 | String apiName; 10 | String symbol; 11 | Price price; 12 | double dayChange; 13 | double weekChange; 14 | }; 15 | 16 | // ---------------------------- 17 | // Coin id list - adjust it to meet your interests 18 | // 19 | // Put your cryptocurrencies in the array below. 20 | // Get id of your coin here: https://api.coingecko.com/api/v3/coins/list?include_platform=false 21 | // ---------------------------- 22 | 23 | Crypto cryptos[] = { 24 | {"bitcoin"}, 25 | {"ethereum"}, 26 | {"dogecoin"}, 27 | {"tether"}, 28 | {"bitcoin-cash"}, 29 | }; 30 | 31 | int cryptosCount = (sizeof(cryptos) / sizeof(cryptos[0])); 32 | -------------------------------------------------------------------------------- /Crypto_Currency_-_Serial_Monitor/Crypto_Currency_-_Serial_Monitor.ino: -------------------------------------------------------------------------------- 1 | /*\ 2 | * 3 | * This is the code for the project 4 | * 5 | * "Crypto Currency Monitor using ESP32 & E-Paper Display" 6 | * 7 | * 8 | * To watch the full tutorial video, just head on to our YouTube channel 9 | * 10 | * https://www.youtube.com/techiesms 11 | * 12 | * 13 | * techiesms 14 | * explore | learn | share 15 | * 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "cryptos.h" 24 | #include "coingecko-api.h" 25 | 26 | // ---------------------------- 27 | // Configurations - Update these 28 | // ---------------------------- 29 | 30 | const char *ssid = "SSID"; 31 | const char *password = "PASS"; 32 | unsigned long secondsForEachCrypto = 5; 33 | 34 | void setup() 35 | { 36 | Serial.begin(115200); 37 | 38 | connectToWifi(); 39 | 40 | delay(4000); 41 | } 42 | 43 | void loop() 44 | { 45 | downloadBaseData("inr"); 46 | delay(1000); 47 | downloadBtcAndEthPrice(); 48 | for (int i = 0; i < cryptosCount; i++) 49 | { 50 | renderCryptoCard(cryptos[i]); 51 | delay(secondsForEachCrypto * 1000); 52 | } 53 | } 54 | 55 | void renderCryptoCard(Crypto crypto) 56 | { 57 | 58 | Serial.print("Crypto Name - "); Serial.println(crypto.symbol); 59 | 60 | Serial.print("price usd - "); Serial.println(formatCurrency(crypto.price.inr)); 61 | 62 | Serial.print("Day change - "); Serial.println(formatPercentageChange(crypto.dayChange)); 63 | 64 | Serial.print("Week change - "); Serial.println(formatPercentageChange(crypto.weekChange)); 65 | 66 | Serial.print("Price in Bitcoin - "); Serial.println(crypto.price.btc); 67 | 68 | Serial.print("Price in ETH - "); Serial.println(crypto.price.eth); 69 | 70 | } 71 | 72 | 73 | 74 | void connectToWifi() 75 | { 76 | WiFi.begin(ssid, password); 77 | String dots[3] = {".", "..", "..."}; 78 | int numberOfDots = 1; 79 | 80 | //tft.setTextColor(//tft_WHITE, //tft_BLACK); 81 | while (WiFi.status() != WL_CONNECTED) 82 | { 83 | 84 | Serial.println("Connecting to WiFi"); 85 | if (numberOfDots == 3) 86 | { 87 | numberOfDots = 0; 88 | } 89 | else 90 | { 91 | numberOfDots++; 92 | } 93 | 94 | delay(300); 95 | //tft.fillScreen(//tft_BLACK); 96 | } 97 | 98 | Serial.println("Connected!!!_______________"); 99 | 100 | } 101 | 102 | String formatCurrency(double price) 103 | { 104 | int digitsAfterDecimal = 3; 105 | 106 | if (price >= 1000) 107 | { 108 | digitsAfterDecimal = 0; 109 | } 110 | else if (price >= 100) 111 | { 112 | digitsAfterDecimal = 1; 113 | } 114 | else if (price >= 1) 115 | { 116 | digitsAfterDecimal = 2; 117 | } 118 | else if (price < 0.001) 119 | { 120 | digitsAfterDecimal = 4; 121 | } 122 | 123 | return String(price, digitsAfterDecimal); 124 | } 125 | 126 | String formatPercentageChange(double change) 127 | { 128 | 129 | 130 | double absChange = change; 131 | 132 | if (change < 0) 133 | { 134 | absChange = -change; 135 | } 136 | 137 | if (absChange > 100) { 138 | return String(absChange, 0) + "%"; 139 | } else if (absChange >= 10) { 140 | return String(absChange, 1) + "%"; 141 | } else { 142 | return String(absChange) + "%"; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /Crypto_Currency_-_ePaper/coingecko-api.h: -------------------------------------------------------------------------------- 1 | // ---------------------------- 2 | // Functions used to download data from coingecko retrieve are separated in this file 3 | // ---------------------------- 4 | 5 | 6 | 7 | const char* rootCACertificate = \ 8 | "-----BEGIN CERTIFICATE-----\n" \ 9 | "MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ\n" \ 10 | "RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD\n" \ 11 | "VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX\n" \ 12 | "DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y\n" \ 13 | "ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy\n" \ 14 | "VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr\n" \ 15 | "mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr\n" \ 16 | "IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK\n" \ 17 | "mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\n" \ 18 | "XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy\n" \ 19 | "dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye\n" \ 20 | "jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1\n" \ 21 | "BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3\n" \ 22 | "DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92\n" \ 23 | "9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx\n" \ 24 | "jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0\n" \ 25 | "Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz\n" \ 26 | "ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\n" \ 27 | "R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\n" \ 28 | "-----END CERTIFICATE-----"; 29 | 30 | 31 | 32 | 33 | HTTPClient http; 34 | WiFiClientSecure client; 35 | 36 | const char *coingeckoSslFingerprint = "8925605d5044fcc0852b98d7d3665228684de6e2"; 37 | 38 | String combineCryptoCurrencies() 39 | { 40 | String cryptosString = ""; 41 | 42 | for (int i = 0; i < cryptosCount; i++) 43 | { 44 | cryptosString += cryptos[i].apiName; 45 | 46 | if (i != cryptosCount - 1) 47 | { 48 | cryptosString += "%2C"; 49 | } 50 | } 51 | 52 | return cryptosString; 53 | } 54 | 55 | int getCryptoIndexById(String id) 56 | { 57 | for (int i = 0; i < cryptosCount; i++) 58 | { 59 | if (cryptos[i].apiName == id) 60 | return i; 61 | } 62 | } 63 | 64 | void downloadBtcAndEthPrice() 65 | { 66 | 67 | 68 | //client.setFingerprint(coingeckoSslFingerprint); 69 | http.useHTTP10(true); 70 | client.setCACert(rootCACertificate); 71 | 72 | String apiUrl = "https://api.coingecko.com/api/v3/simple/price?ids=" + combineCryptoCurrencies() + "&vs_currencies=btc%2Ceth"; 73 | 74 | client.connect("api.coingecko.com", 443); 75 | http.begin(client, apiUrl); 76 | 77 | int code = http.GET(); 78 | if (code != HTTP_CODE_OK) 79 | { 80 | Serial.println("Error connecting to API while downloading BTC and ETH data"); 81 | Serial.println(code); 82 | return; 83 | } 84 | 85 | Serial.println("Successfuly downloaded BTC and ETH data"); 86 | 87 | StaticJsonDocument<512> filter; 88 | 89 | for (int i = 0; i < cryptosCount; i++) 90 | { 91 | filter[cryptos[i].apiName]["btc"] = true; 92 | filter[cryptos[i].apiName]["eth"] = true; 93 | } 94 | 95 | DynamicJsonDocument doc(4096); 96 | DeserializationError error = deserializeJson(doc, http.getStream(), DeserializationOption::Filter(filter)); 97 | 98 | if (error) 99 | { 100 | Serial.print(F("deserializeJson() failed: ")); 101 | Serial.println(error.f_str()); 102 | } 103 | 104 | for (int i = 0; i < cryptosCount; i++) 105 | { 106 | JsonObject json = doc[cryptos[i].apiName]; 107 | String btcPrice = json["btc"]; 108 | String ethPrice = json["eth"]; 109 | 110 | cryptos[i].price.btc = btcPrice; 111 | cryptos[i].price.eth = ethPrice; 112 | } 113 | 114 | http.end(); 115 | client.stop(); 116 | } 117 | 118 | void downloadBaseData(String vsCurrency) 119 | { 120 | http.useHTTP10(true); 121 | client.setCACert(rootCACertificate); 122 | //client.setFingerprint(coingeckoSslFingerprint); 123 | 124 | String apiUrl = "https://api.coingecko.com/api/v3/coins/markets?vs_currency=" + vsCurrency + "&ids=" + combineCryptoCurrencies() + "&order=market_cap_desc&per_page=100&page=1&sparkline=false&price_change_percentage=24h%2C7d"; 125 | 126 | client.connect("api.coingecko.com", 443); 127 | 128 | http.begin(client, apiUrl); 129 | 130 | int code = http.GET(); 131 | if (code != HTTP_CODE_OK) 132 | { 133 | Serial.println("Error connecting to API while downloading base data"); 134 | Serial.println(code); 135 | return; 136 | } 137 | 138 | Serial.println("Successfuly downloaded BASE data"); 139 | 140 | StaticJsonDocument<512> filter; 141 | 142 | for (int i = 0; i < cryptosCount; i++) 143 | { 144 | filter[i]["id"] = true; 145 | filter[i]["symbol"] = true; 146 | filter[i]["current_price"] = true; 147 | filter[i]["price_change_percentage_24h_in_currency"] = true; 148 | filter[i]["price_change_percentage_7d_in_currency"] = true; 149 | } 150 | 151 | DynamicJsonDocument doc(4096); 152 | DeserializationError error = deserializeJson(doc, http.getStream(), DeserializationOption::Filter(filter)); 153 | 154 | if (error) 155 | { 156 | Serial.print(F("deserializeJson() failed: ")); 157 | Serial.println(error.f_str()); 158 | } 159 | 160 | for (int i = 0; i < cryptosCount; i++) 161 | { 162 | JsonObject json = doc[i]; 163 | String id = json["id"]; 164 | int cryptoIndex = getCryptoIndexById(id); 165 | 166 | double currentPrice = json["current_price"]; 167 | cryptos[cryptoIndex].price.inr = currentPrice; 168 | 169 | String symbol = json["symbol"]; 170 | symbol.toUpperCase(); 171 | double dayChange = json["price_change_percentage_24h_in_currency"]; 172 | double weekChange = json["price_change_percentage_7d_in_currency"]; 173 | 174 | cryptos[cryptoIndex].symbol = symbol; 175 | cryptos[cryptoIndex].dayChange = dayChange; 176 | cryptos[cryptoIndex].weekChange = weekChange; 177 | } 178 | 179 | http.end(); 180 | client.stop(); 181 | } 182 | -------------------------------------------------------------------------------- /Crypto_Currency_-_Serial_Monitor/coingecko-api.h: -------------------------------------------------------------------------------- 1 | // ---------------------------- 2 | // Functions used to download data from coingecko retrieve are separated in this file 3 | // ---------------------------- 4 | 5 | 6 | 7 | const char* rootCACertificate = \ 8 | "-----BEGIN CERTIFICATE-----\n" \ 9 | "MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ\n" \ 10 | "RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD\n" \ 11 | "VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX\n" \ 12 | "DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y\n" \ 13 | "ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy\n" \ 14 | "VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr\n" \ 15 | "mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr\n" \ 16 | "IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK\n" \ 17 | "mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\n" \ 18 | "XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy\n" \ 19 | "dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye\n" \ 20 | "jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1\n" \ 21 | "BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3\n" \ 22 | "DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92\n" \ 23 | "9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx\n" \ 24 | "jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0\n" \ 25 | "Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz\n" \ 26 | "ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\n" \ 27 | "R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\n" \ 28 | "-----END CERTIFICATE-----"; 29 | 30 | 31 | 32 | 33 | HTTPClient http; 34 | WiFiClientSecure client; 35 | 36 | const char *coingeckoSslFingerprint = "8925605d5044fcc0852b98d7d3665228684de6e2"; 37 | 38 | String combineCryptoCurrencies() 39 | { 40 | String cryptosString = ""; 41 | 42 | for (int i = 0; i < cryptosCount; i++) 43 | { 44 | cryptosString += cryptos[i].apiName; 45 | 46 | if (i != cryptosCount - 1) 47 | { 48 | cryptosString += "%2C"; 49 | } 50 | } 51 | 52 | return cryptosString; 53 | } 54 | 55 | int getCryptoIndexById(String id) 56 | { 57 | for (int i = 0; i < cryptosCount; i++) 58 | { 59 | if (cryptos[i].apiName == id) 60 | return i; 61 | } 62 | } 63 | 64 | void downloadBtcAndEthPrice() 65 | { 66 | 67 | 68 | //client.setFingerprint(coingeckoSslFingerprint); 69 | http.useHTTP10(true); 70 | client.setCACert(rootCACertificate); 71 | 72 | String apiUrl = "https://api.coingecko.com/api/v3/simple/price?ids=" + combineCryptoCurrencies() + "&vs_currencies=btc%2Ceth"; 73 | 74 | client.connect("api.coingecko.com", 443); 75 | http.begin(client, apiUrl); 76 | 77 | int code = http.GET(); 78 | if (code != HTTP_CODE_OK) 79 | { 80 | Serial.println("Error connecting to API while downloading BTC and ETH data"); 81 | Serial.println(code); 82 | return; 83 | } 84 | 85 | Serial.println("Successfuly downloaded BTC and ETH data"); 86 | 87 | StaticJsonDocument<512> filter; 88 | 89 | for (int i = 0; i < cryptosCount; i++) 90 | { 91 | filter[cryptos[i].apiName]["btc"] = true; 92 | filter[cryptos[i].apiName]["eth"] = true; 93 | } 94 | 95 | DynamicJsonDocument doc(4096); 96 | DeserializationError error = deserializeJson(doc, http.getStream(), DeserializationOption::Filter(filter)); 97 | 98 | if (error) 99 | { 100 | Serial.print(F("deserializeJson() failed: ")); 101 | Serial.println(error.f_str()); 102 | } 103 | 104 | for (int i = 0; i < cryptosCount; i++) 105 | { 106 | JsonObject json = doc[cryptos[i].apiName]; 107 | String btcPrice = json["btc"]; 108 | String ethPrice = json["eth"]; 109 | 110 | cryptos[i].price.btc = btcPrice; 111 | cryptos[i].price.eth = ethPrice; 112 | } 113 | 114 | http.end(); 115 | client.stop(); 116 | } 117 | 118 | void downloadBaseData(String vsCurrency) 119 | { 120 | http.useHTTP10(true); 121 | client.setCACert(rootCACertificate); 122 | //client.setFingerprint(coingeckoSslFingerprint); 123 | 124 | String apiUrl = "https://api.coingecko.com/api/v3/coins/markets?vs_currency=" + vsCurrency + "&ids=" + combineCryptoCurrencies() + "&order=market_cap_desc&per_page=100&page=1&sparkline=false&price_change_percentage=24h%2C7d"; 125 | 126 | client.connect("api.coingecko.com", 443); 127 | 128 | http.begin(client, apiUrl); 129 | 130 | int code = http.GET(); 131 | if (code != HTTP_CODE_OK) 132 | { 133 | Serial.println("Error connecting to API while downloading base data"); 134 | Serial.println(code); 135 | return; 136 | } 137 | 138 | Serial.println("Successfuly downloaded BASE data"); 139 | 140 | StaticJsonDocument<512> filter; 141 | 142 | for (int i = 0; i < cryptosCount; i++) 143 | { 144 | filter[i]["id"] = true; 145 | filter[i]["symbol"] = true; 146 | filter[i]["current_price"] = true; 147 | filter[i]["price_change_percentage_24h_in_currency"] = true; 148 | filter[i]["price_change_percentage_7d_in_currency"] = true; 149 | } 150 | 151 | DynamicJsonDocument doc(4096); 152 | DeserializationError error = deserializeJson(doc, http.getStream(), DeserializationOption::Filter(filter)); 153 | 154 | if (error) 155 | { 156 | Serial.print(F("deserializeJson() failed: ")); 157 | Serial.println(error.f_str()); 158 | } 159 | 160 | for (int i = 0; i < cryptosCount; i++) 161 | { 162 | JsonObject json = doc[i]; 163 | String id = json["id"]; 164 | int cryptoIndex = getCryptoIndexById(id); 165 | 166 | double currentPrice = json["current_price"]; 167 | cryptos[cryptoIndex].price.inr = currentPrice; 168 | 169 | String symbol = json["symbol"]; 170 | symbol.toUpperCase(); 171 | double dayChange = json["price_change_percentage_24h_in_currency"]; 172 | double weekChange = json["price_change_percentage_7d_in_currency"]; 173 | 174 | cryptos[cryptoIndex].symbol = symbol; 175 | cryptos[cryptoIndex].dayChange = dayChange; 176 | cryptos[cryptoIndex].weekChange = weekChange; 177 | } 178 | 179 | http.end(); 180 | client.stop(); 181 | } 182 | -------------------------------------------------------------------------------- /Crypto_Currency_-_ePaper/Crypto_Currency_-_ePaper.ino: -------------------------------------------------------------------------------- 1 | /*\ 2 | * 3 | * This is the code for the project 4 | * 5 | * "Crypto Currency Monitor using ESP32 & E-Paper Display" 6 | * 7 | * 8 | * To watch the full tutorial video, just head on to our YouTube channel 9 | * 10 | * https://www.youtube.com/techiesms 11 | * 12 | * 13 | * techiesms 14 | * explore | learn | share 15 | * 16 | * 17 | */ 18 | #ifndef BOARD_HAS_PSRAM 19 | #error "Please enable PSRAM !!!" 20 | #endif 21 | 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "cryptos.h" 28 | #include "coingecko-api.h" 29 | #include 30 | #include 31 | #include "freertos/FreeRTOS.h" 32 | #include "freertos/task.h" 33 | #include "epd_driver.h" 34 | #include "firasans.h" 35 | #include "esp_adc_cal.h" 36 | #include 37 | #include 38 | #include 39 | 40 | 41 | #define BATT_PIN 36 42 | #define SD_MISO 12 43 | #define SD_MOSI 13 44 | #define SD_SCLK 14 45 | #define SD_CS 15 46 | 47 | int cursor_x ; 48 | int cursor_y ; 49 | 50 | uint8_t *framebuffer; 51 | int vref = 1100; 52 | 53 | // ---------------------------- 54 | // Configurations - Update these 55 | // ---------------------------- 56 | 57 | const char *ssid = "SSID"; 58 | const char *password = "PASS"; 59 | 60 | 61 | // ---------------------------- 62 | // End of area you need to change 63 | // ---------------------------- 64 | 65 | 66 | void setup() 67 | { 68 | char buf[128]; 69 | 70 | Serial.begin(115200); 71 | 72 | 73 | connectToWifi(); 74 | 75 | // Correct the ADC reference voltage 76 | esp_adc_cal_characteristics_t adc_chars; 77 | esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 1100, &adc_chars); 78 | if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) { 79 | Serial.printf("eFuse Vref:%u mV", adc_chars.vref); 80 | vref = adc_chars.vref; 81 | } 82 | 83 | epd_init(); 84 | 85 | framebuffer = (uint8_t *)ps_calloc(sizeof(uint8_t), EPD_WIDTH * EPD_HEIGHT / 2); 86 | if (!framebuffer) { 87 | Serial.println("alloc memory failed !!!"); 88 | while (1); 89 | } 90 | memset(framebuffer, 0xFF, EPD_WIDTH * EPD_HEIGHT / 2); 91 | 92 | epd_poweron(); 93 | epd_clear(); 94 | 95 | epd_poweroff(); 96 | 97 | epd_poweron(); 98 | 99 | 100 | 101 | } 102 | 103 | void loop() 104 | { 105 | downloadBaseData("inr"); 106 | delay(1000); 107 | downloadBtcAndEthPrice(); 108 | title(); 109 | for (int i = 0; i < cryptosCount; i++) 110 | { 111 | cursor_y = (50 * (i + 3)); 112 | renderCryptoCard(cryptos[i]); 113 | } 114 | delay(5000); 115 | } 116 | 117 | void title() 118 | { 119 | 120 | cursor_x = 20; 121 | cursor_y = 50; 122 | char *sym = "Symbol"; 123 | writeln((GFXfont *)&FiraSans, sym, &cursor_x, &cursor_y, NULL); 124 | 125 | cursor_x = 290; 126 | cursor_y = 50; 127 | char *prc = "Price"; 128 | writeln((GFXfont *)&FiraSans, prc, &cursor_x, &cursor_y, NULL); 129 | 130 | cursor_x = 520; 131 | cursor_y = 50; 132 | char *da = "Day(%)"; 133 | writeln((GFXfont *)&FiraSans, da, &cursor_x, &cursor_y, NULL); 134 | 135 | cursor_x = 790; 136 | cursor_y = 50; 137 | char *we = "Week(%)"; 138 | writeln((GFXfont *)&FiraSans, we, &cursor_x, &cursor_y, NULL); 139 | 140 | 141 | } 142 | 143 | void renderCryptoCard(Crypto crypto) 144 | { 145 | 146 | 147 | 148 | Serial.print("Crypto Name - "); Serial.println(crypto.symbol); 149 | 150 | cursor_x = 50; 151 | 152 | char *string1 = &crypto.symbol[0]; 153 | 154 | writeln((GFXfont *)&FiraSans, string1, &cursor_x, &cursor_y, NULL); 155 | 156 | cursor_x = 220; 157 | 158 | String Str = (String)(crypto.price.inr); 159 | char* string2 = &Str[0]; 160 | 161 | Serial.print("price usd - "); Serial.println(Str); 162 | 163 | Rect_t area = { 164 | .x = cursor_x, 165 | .y = cursor_y-40, 166 | .width = 320, 167 | .height = 50, 168 | }; 169 | 170 | epd_clear_area(area); 171 | 172 | writeln((GFXfont *)&FiraSans, string2, &cursor_x, &cursor_y, NULL); 173 | 174 | Serial.print("Day change - "); Serial.println(formatPercentageChange(crypto.dayChange)); 175 | 176 | cursor_x = 530; 177 | 178 | Rect_t area1 = { 179 | .x = cursor_x, 180 | .y = cursor_y-40, 181 | .width = 150, 182 | .height = 50, 183 | }; 184 | 185 | epd_clear_area(area1); 186 | Str = (String)(crypto.dayChange); 187 | char* string3 = &Str[0]; 188 | 189 | writeln((GFXfont *)&FiraSans, string3, &cursor_x, &cursor_y, NULL); 190 | 191 | 192 | Serial.print("Week change - "); Serial.println(formatPercentageChange(crypto.weekChange)); 193 | 194 | cursor_x = 800; 195 | 196 | Rect_t area2 = { 197 | .x = cursor_x, 198 | .y = cursor_y-40, 199 | .width = 150, 200 | .height = 50, 201 | }; 202 | 203 | epd_clear_area(area2); 204 | 205 | Str = (String)(crypto.weekChange); 206 | char* string4 = &Str[0]; 207 | 208 | writeln((GFXfont *)&FiraSans, string4, &cursor_x, &cursor_y, NULL); 209 | 210 | } 211 | 212 | 213 | void connectToWifi() 214 | { 215 | WiFi.begin(ssid, password); 216 | String dots[3] = {".", "..", "..."}; 217 | int numberOfDots = 1; 218 | 219 | //tft.setTextColor(//tft_WHITE, //tft_BLACK); 220 | while (WiFi.status() != WL_CONNECTED) 221 | { 222 | //tft.drawCentreString("Connecting to WiFi " + dots[numberOfDots - 1], 120, 120, 2); 223 | Serial.println("Connecting to WiFi"); 224 | if (numberOfDots == 3) 225 | { 226 | numberOfDots = 0; 227 | } 228 | else 229 | { 230 | numberOfDots++; 231 | } 232 | 233 | delay(300); 234 | //tft.fillScreen(//tft_BLACK); 235 | } 236 | 237 | Serial.println("Connected!!!_______________"); 238 | 239 | } 240 | 241 | 242 | 243 | String formatPercentageChange(double change) 244 | { 245 | 246 | 247 | double absChange = change; 248 | 249 | if (change < 0) 250 | { 251 | absChange = -change; 252 | } 253 | 254 | if (absChange > 100) { 255 | return String(absChange, 0) + "%"; 256 | } else if (absChange >= 10) { 257 | return String(absChange, 1) + "%"; 258 | } else { 259 | return String(absChange) + "%"; 260 | } 261 | } 262 | --------------------------------------------------------------------------------