Mini DUCO Mining Rig esp8266, Mining Duino Coin dengan Esp01 board
Sebelumnya sudah kita buatkan langkah-langkahnya untuk melakukan mining Duino Coin menggunakan mikrokontroller berbasis esp8266 menggunakan nodeMCU pada postingan ini. Memahami dari konsep tersebut, saya berpikir untuk membuat mining rig dengan menggunakan esp-01, toh sama-sama keluarga esp8266. Nah, mengapa ESP-01? Dalam proses mining Duino Coin, hal yang perlu dimiliki oleh perangkat penambang adalah konektivitas dengan internet dan catu daya yang memadai. Dalam 2 hal tersebut, ESP-01 sudah dapat melakukannya. Selain itu, harga ESP-01 yang lebih murah dan dimensinya yang kecil menjadikan ESP-01 layak kita coba untuk dijadikan perangkat penambang.
Apa itu Mining RIG?
Secara umum mining rig adalah perangkat "spesial" yang dikhususkan untuk proses mining. Nah spesial yang seperti apa? Special disini adalah desain yang dikususkan yang sudah menggambarkan berapa hashrate yang dihasilkan, berpa total jumlah penambang, berapa total daya yang digunakan, dll. Saat kita menggunakan 1 perangkat penambang, biasanya kita akan mendapatkan hashrate yang rendah. Hash Rate adalah ukuran kekuatan komputasi dalam jaringan cryptocurrency proof-of-work (PoW). Semakin besar hashrate maka semakin cepat proses penambangan yang dilakukan. Tetapi hal tersebut dianggap sebagai tindakan yang tidak fair oleh sistem DUCO. Untuk mencegah orang membuat ladang/pool penambangan besar yang melarang pengguna "biasa" untuk menambang, kami telah membuat sistem yang disebut penurunan efisiensi Kolka, yang menyebabkan setiap penambang tambahan mendapat penghasilan sedikit lebih sedikit dari yang sebelumnya. Rumusnya adalah efisiensi perangkat penambang terakhir * 100 - penurunan %, penurunan untuk AVR dan ESP adalah 4% dan untuk PC 20%. Nah rumus tersebut dikenal dengan Efficiency drop, yang intinya dalam melakukan mining DUCO apabila kita menggunakan banyak perangkat, maka hasilnya juga gak akan signifikan.
Desain perangkat
Dalam membuat perangkat ini, diperlukan bahan-bahan:
- Modul ESP-01 atau ESP-01S => cek tokped
- ESP-01 Programer adapter (Buat upload program ) => cek tokped
- Modul Kit Step Down AMS1117 3.3V => cek tokped
- Power Supply 5 V minimal arus 1A => cek tokped
Dari skematic dasar dapat dilihat bahwa hanya 3 pin yang digunakan yaitu GND, VCC dan CH_PD. pin CH_PD dihubungkan ke VCC dimaksudkan agar pin CH_PD bernilai High yang dimaksudkan Chip dalam kondisi aktif. Nah dari rangkaian dasar diatas, kita kembangkan untuk dihubungkan dengan 4 buah modul ESP01 di setiap modul AMS117.
Upload Program ke Board ESP-01
Setelah perangkat selesai di buat, langkah selanjutnya ialah memasukkan program ke modul ESP-01. Ada beberapa hal yang perlu diperhatikan dalam melakukan proses pemrograman ini:
- Modul ESP 01 tidak memiliki interface USB sehingga tidak bersifat plug n run seperti modul wemos, node MCU atau esp 32. Dengan demikian kita memerlukan bantuan ESP-01 Programer adapter untuk proses ini.
- Pada dasarnya modul ESP01 merupakan modul Wifi yang diperuntukkan sebagai pembantu perangkat mikrokontroller seperti Arduino UNO/NANO/MEGA untuk terkoneksi dengan jaringan wifi. Secara default dipasaran, modul ESP-01 telah diflash dengan firmware AT COMMAND. Nah dalam kondisi default ini, kita tidak dapat melakukan upload program ke modul ESP-01. Kita harus flash dulu modul ESP-01 menggunakan firmware nodeMCU. Cara flashing nya dapat di lihat ditutorial ini.
Dalam tutorial ini, saya asumsikan bahwa modul-modul ESP01 yang akan kiga gunakan sebagai penambang sudah diflash dengan firmware NodeMCU terlebih dahulu. Untuk program nya dapat kita gunakan program dibawah dengan mengubah beberapa nilai variabel. Pastikan kita sudah memiliki akun Duco Wallet. Silahkan simak post ini untuk cara registrasi Duco Wallet.
/*
____ __ __ ____ _ _ _____ ___ _____ ____ _ _
( _ \( )( )(_ _)( \( )( _ )___ / __)( _ )(_ _)( \( )
)(_) ))(__)( _)(_ ) ( )(_)((___)( (__ )(_)( _)(_ ) (
(____/(______)(____)(_)\_)(_____) \___)(_____)(____)(_)\_)
Official code for ESP8266 boards version 3.5
Duino-Coin Team & Community 2019-2022 © MIT Licensed
https://duinocoin.com
https://github.com/revoxhere/duino-coin
If you don't know where to start, visit official website and navigate to
the Getting Started page. Have fun mining!
*/
/* If optimizations cause problems, change them to -O0 (the default)
NOTE: For even better optimizations also edit your Crypto.h file.
On linux that file can be found in the following location:
~/.arduino15//packages/esp8266/hardware/esp8266/3.0.2/cores/esp8266/ */
#pragma GCC optimize ("-Ofast")
/* If during compilation the line below causes a
"fatal error: arduinoJson.h: No such file or directory"
message to occur; it means that you do NOT have the
ArduinoJSON library installed. To install it,
go to the below link and follow the instructions:
https://github.com/revoxhere/duino-coin/issues/832 */
#include <ArduinoJson.h>
/* If during compilation the line below causes a
"fatal error: Crypto.h: No such file or directory"
message to occur; it means that you do NOT have the
latest version of the ESP8266/Arduino Core library.
To install/upgrade it, go to the below link and
follow the instructions of the readme file:
https://github.com/esp8266/Arduino */
#include <bearssl/bearssl.h>
//#include <TypeConversion.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <Ticker.h>
#include <ESP8266WebServer.h>
// Uncomment the line below if you wish to use a DHT sensor (Duino IoT beta)
// #define USE_DHT
// Uncomment the line below if you wish to register for IOT updates with an MQTT broker
// #define USE_MQTT
// If you don't know what MQTT means check this link:
// https://www.techtarget.com/iotagenda/definition/MQTT-MQ-Telemetry-Transport
#ifdef USE_DHT
float temp = 0.0;
float hum = 0.0;
// Install "DHT sensor library" if you get an error
#include <DHT.h>
// Change D3 to the pin you've connected your sensor to
#define DHTPIN D3
// Set DHT11 or DHT22 accordingly
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
#endif
#ifdef USE_MQTT
// Install "PubSubClient" if you get an error
#include <PubSubClient.h>
long lastMsg = 0;
// Change the part in brackets to your MQTT broker address
#define mqtt_server "broker.hivemq.com"
// broker.hivemq.com is for testing purposes, change it to your broker address
// Change this to your MQTT broker port
#define mqtt_port 1883
// If you want to use user and password for your MQTT broker, uncomment the line below
// #define mqtt_use_credentials
// Change the part in brackets to your MQTT broker username
#define mqtt_user "My cool mqtt username"
// Change the part in brackets to your MQTT broker password
#define mqtt_password "My secret mqtt pass"
// Change this if you want to send data to the topic every X milliseconds
#define mqtt_update_time 5000
// Change the part in brackets to your MQTT humidity topic
#define humidity_topic "sensor/humidity"
// Change the part in brackets to your MQTT temperature topic
#define temperature_topic "sensor/temperature"
WiFiClient espClient;
PubSubClient mqttClient(espClient);
void mqttReconnect()
{
// Loop until we're reconnected
while (!mqttClient.connected())
{
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
#ifdef mqtt_use_credentials
if (mqttClient.connect("ESP8266Client", mqtt_user, mqtt_password))
#else
if (mqttClient.connect(clientId.c_str()))
#endif
{
Serial.println("connected");
}
else
{
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
#endif
namespace
{
// Change the part in brackets to your Duino-Coin username
const char *DUCO_USER = "**********"; //user dari duco wallet
// Change the part in brackets to your mining key (if you have enabled it in the wallet)
const char *MINER_KEY = "**********"; //mining key ( lihat di duco wallet)
// Change the part in brackets to your WiFi name
const char *SSID = "**********"; //nama wifi yang akan digunakan
// Change the part in brackets to your WiFi password
const char *PASSWORD = "**********"; //password wifinya
// Change the part in brackets if you want to set a custom miner name (use Auto to autogenerate, None for no name)
const char *RIG_IDENTIFIER = "**********"; //nama perangkat, harus beda tiap perangkat
// Set to true to use the 160 MHz overclock mode (and not get the first share rejected)
const bool USE_HIGHER_DIFF = true;
// Set to true if you want to host the dashboard page (available on ESPs IP address)
const bool WEB_DASHBOARD = false;
// Set to true if you want to update hashrate in browser without reloading the page
const bool WEB_HASH_UPDATER = false;
// Set to false if you want to disable the onboard led blinking when finding shares
const bool LED_BLINKING = true;
/* Do not change the lines below. These lines are static and dynamic variables
that will be used by the program for counters and measurements. */
const char * DEVICE = "ESP8266";
const char * POOLPICKER_URL[] = {"https://server.duinocoin.com/getPool"};
const char * MINER_BANNER = "Official ESP8266 Miner";
const char * MINER_VER = "3.5";
unsigned int share_count = 0;
unsigned int port = 0;
unsigned int difficulty = 0;
float hashrate = 0;
String AutoRigName = "";
String host = "";
String node_id = "";
const char WEBSITE[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<!--
Duino-Coin self-hosted dashboard
MIT licensed
Duino-Coin official 2019-2022
https://github.com/revoxhere/duino-coin
https://duinocoin.com
-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Duino-Coin @@DEVICE@@ dashboard</title>
<link rel="stylesheet" href="https://server.duinocoin.com/assets/css/mystyles.css">
<link rel="shortcut icon" href="https://github.com/revoxhere/duino-coin/blob/master/Resources/duco.png?raw=true">
<link rel="icon" type="image/png" href="https://github.com/revoxhere/duino-coin/blob/master/Resources/duco.png?raw=true">
</head>
<body>
<section class="section">
<div class="container">
<h1 class="title">
<img class="icon" src="https://github.com/revoxhere/duino-coin/blob/master/Resources/duco.png?raw=true">
@@DEVICE@@ <small>(@@ID@@)</small>
</h1>
<p class="subtitle">
Self-hosted, lightweight, official dashboard for your <strong>Duino-Coin</strong> miner
</p>
</div>
<br>
<div class="container">
<div class="columns">
<div class="column">
<div class="box">
<p class="subtitle">
Mining statistics
</p>
<div class="columns is-multiline">
<div class="column" style="min-width:15em">
<div class="title is-size-5 mb-0">
<span id="hashratex">@@HASHRATE@@</span>kH/s
</div>
<div class="heading is-size-5">
Hashrate
</div>
</div>
<div class="column" style="min-width:15em">
<div class="title is-size-5 mb-0">
@@DIFF@@
</div>
<div class="heading is-size-5">
Difficulty
</div>
</div>
<div class="column" style="min-width:15em">
<div class="title is-size-5 mb-0">
@@SHARES@@
</div>
<div class="heading is-size-5">
Shares
</div>
</div>
<div class="column" style="min-width:15em">
<div class="title is-size-5 mb-0">
@@NODE@@
</div>
<div class="heading is-size-5">
Node
</div>
</div>
</div>
</div>
</div>
<div class="column">
<div class="box">
<p class="subtitle">
Device information
</p>
<div class="columns is-multiline">
<div class="column" style="min-width:15em">
<div class="title is-size-5 mb-0">
@@DEVICE@@
</div>
<div class="heading is-size-5">
Device type
</div>
</div>
<div class="column" style="min-width:15em">
<div class="title is-size-5 mb-0">
@@ID@@
</div>
<div class="heading is-size-5">
Device ID
</div>
</div>
<div class="column" style="min-width:15em">
<div class="title is-size-5 mb-0">
@@MEMORY@@
</div>
<div class="heading is-size-5">
Free memory
</div>
</div>
<div class="column" style="min-width:15em">
<div class="title is-size-5 mb-0">
@@VERSION@@
</div>
<div class="heading is-size-5">
Miner version
</div>
</div>
)====="
#ifdef USE_DHT
" <div class=\"column\" style=\"min-width:15em\">"
" <div class=\"title is-size-5 mb-0\">"
" @@TEMP@@ °C"
" </div>"
" <div class=\"heading is-size-5\">"
" Temperature"
" </div>"
" </div>"
" <div class=\"column\" style=\"min-width:15em\">"
" <div class=\"title is-size-5 mb-0\">"
" @@HUM@@ %"
" </div>"
" <div class=\"heading is-size-5\">"
" Humidity"
" </div>"
" </div>"
#endif
R"=====(
</div>
</div>
</div>
</div>
<br>
<div class="has-text-centered">
<div class="title is-size-6 mb-0">
Hosted on
<a href="http://@@IP_ADDR@@">
http://<b>@@IP_ADDR@@</b>
</a>
•
<a href="https://duinocoin.com">
duinocoin.com
</a>
•
<a href="https://github.com/revoxhere/duino-coin">
github.com/revoxhere/duino-coin
</a>
</div>
</div>
</div>
<script>
setInterval(function(){
getData();
}, 3000);
function getData() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("hashratex").innerHTML = this.responseText;
}
};
xhttp.open("GET", "hashrateread", true);
xhttp.send();
}
</script>
</section>
</body>
</html>
)=====";
ESP8266WebServer server(80);
void hashupdater(){ //update hashrate every 3 sec in browser without reloading page
server.send(200, "text/plain", String(hashrate / 1000));
Serial.println("Update hashrate on page");
};
void UpdateHostPort(String input) {
// Thanks @ricaun for the code
DynamicJsonDocument doc(256);
deserializeJson(doc, input);
const char* name = doc["name"];
host = String((const char*)doc["ip"]);
port = int(doc["port"]);
node_id = String(name);
Serial.println("Poolpicker selected the best mining node: " + node_id);
}
String httpGetString(String URL) {
String payload = "";
WiFiClientSecure client;
client.setInsecure();
HTTPClient http;
if (http.begin(client, URL)) {
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) payload = http.getString();
else Serial.printf("Error fetching node from poolpicker: %s\n", http.errorToString(httpCode).c_str());
http.end();
}
return payload;
}
void UpdatePool() {
String input = "";
int waitTime = 1;
int poolIndex = 0;
int poolSize = sizeof(POOLPICKER_URL) / sizeof(char*);
while (input == "") {
Serial.println("Fetching mining node from the poolpicker in " + String(waitTime) + "s");
input = httpGetString(POOLPICKER_URL[poolIndex]);
poolIndex += 1;
// Check if pool index needs to roll over
if( poolIndex >= poolSize ){
poolIndex %= poolSize;
delay(waitTime * 1000);
// Increase wait time till a maximum of 32 seconds (addresses: Limit connection requests on failure in ESP boards #1041)
waitTime *= 2;
if( waitTime > 32 )
waitTime = 32;
}
}
// Setup pool with new input
UpdateHostPort(input);
}
WiFiClient client;
String client_buffer = "";
String chipID = "";
String START_DIFF = "";
// Loop WDT... please don't feed me...
// See lwdtcb() and lwdtFeed() below
Ticker lwdTimer;
#define LWD_TIMEOUT 20000
unsigned long lwdCurrentMillis = 0;
unsigned long lwdTimeOutMillis = LWD_TIMEOUT;
#define END_TOKEN '\n'
#define SEP_TOKEN ','
#define LED_BUILTIN 2
#define BLINK_SETUP_COMPLETE 2
#define BLINK_CLIENT_CONNECT 3
#define BLINK_RESET_DEVICE 5
void SetupWifi() {
Serial.println("Connecting to: " + String(SSID));
WiFi.mode(WIFI_STA); // Setup ESP in client mode
WiFi.setSleepMode(WIFI_NONE_SLEEP);
WiFi.begin(SSID, PASSWORD);
int wait_passes = 0;
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (++wait_passes >= 10) {
WiFi.begin(SSID, PASSWORD);
wait_passes = 0;
}
}
Serial.println("\n\nSuccessfully connected to WiFi");
Serial.println("Local IP address: " + WiFi.localIP().toString());
Serial.println("Rig name: " + String(RIG_IDENTIFIER));
Serial.println();
UpdatePool();
}
void SetupOTA() {
// Prepare OTA handler
ArduinoOTA.onStart([]() {
Serial.println("Start");
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.setHostname(RIG_IDENTIFIER); // Give port a name not just address
ArduinoOTA.begin();
}
void blink(uint8_t count, uint8_t pin = LED_BUILTIN) {
if (LED_BLINKING){
uint8_t state = HIGH;
for (int x = 0; x < (count << 1); ++x) {
digitalWrite(pin, state ^= HIGH);
delay(50);
}
} else {
digitalWrite(LED_BUILTIN, HIGH);
}
}
void RestartESP(String msg) {
Serial.println(msg);
Serial.println("Restarting ESP...");
blink(BLINK_RESET_DEVICE);
ESP.reset();
}
// Our new WDT to help prevent freezes
// code concept taken from https://sigmdel.ca/michel/program/esp8266/arduino/watchdogs2_en.html
void ICACHE_RAM_ATTR lwdtcb(void) {
if ((millis() - lwdCurrentMillis > LWD_TIMEOUT) || (lwdTimeOutMillis - lwdCurrentMillis != LWD_TIMEOUT))
RestartESP("Loop WDT Failed!");
}
void lwdtFeed(void) {
lwdCurrentMillis = millis();
lwdTimeOutMillis = lwdCurrentMillis + LWD_TIMEOUT;
}
void VerifyWifi() {
while (WiFi.status() != WL_CONNECTED || WiFi.localIP() == IPAddress(0, 0, 0, 0))
WiFi.reconnect();
}
void handleSystemEvents(void) {
VerifyWifi();
ArduinoOTA.handle();
yield();
}
void waitForClientData(void) {
client_buffer = "";
while (client.connected()) {
if (client.available()) {
client_buffer = client.readStringUntil(END_TOKEN);
if (client_buffer.length() == 1 && client_buffer[0] == END_TOKEN)
client_buffer = "???\n"; // NOTE: Should never happen
break;
}
handleSystemEvents();
}
}
void ConnectToServer() {
if (client.connected())
return;
Serial.println("\n\nConnecting to the Duino-Coin server...");
while (!client.connect(host.c_str(), port));
waitForClientData();
Serial.println("Connected to the server. Server version: " + client_buffer );
blink(BLINK_CLIENT_CONNECT); // Sucessfull connection with the server
}
bool max_micros_elapsed(unsigned long current, unsigned long max_elapsed) {
static unsigned long _start = 0;
if ((current - _start) > max_elapsed) {
_start = current;
return true;
}
return false;
}
void dashboard() {
Serial.println("Handling HTTP client");
String s = WEBSITE;
s.replace("@@IP_ADDR@@", WiFi.localIP().toString());
s.replace("@@HASHRATE@@", String(hashrate / 1000));
s.replace("@@DIFF@@", String(difficulty / 100));
s.replace("@@SHARES@@", String(share_count));
s.replace("@@NODE@@", String(node_id));
s.replace("@@DEVICE@@", String(DEVICE));
s.replace("@@ID@@", String(RIG_IDENTIFIER));
s.replace("@@MEMORY@@", String(ESP.getFreeHeap()));
s.replace("@@VERSION@@", String(MINER_VER));
#ifdef USE_DHT
s.replace("@@TEMP@@", String(temp));
s.replace("@@HUM@@", String(hum));
#endif
server.send(200, "text/html", s);
}
} // namespace
// https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TypeConversion.cpp
const char base36Chars[36] PROGMEM = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
const uint8_t base36CharValues[75] PROGMEM {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, // 0 to 9
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0, 0, // Upper case letters
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 // Lower case letters
};
uint8_t *hexStringToUint8Array(const String &hexString, uint8_t *uint8Array, const uint32_t arrayLength) {
assert(hexString.length() >= arrayLength * 2);
for (uint32_t i = 0; i < arrayLength; ++i) {
uint8Array[i] = (pgm_read_byte(base36CharValues + hexString.charAt(i * 2) - '0') << 4) + pgm_read_byte(base36CharValues + hexString.charAt(i * 2 + 1) - '0');
}
return uint8Array;
}
struct MiningJob
{
String last_block_hash;
String expected_hash_str;
uint8_t expected_hash[20];
unsigned int difficulty;
bool parse(char* job_str)
{
String tokens[3];
char *token = strtok(job_str, ",");
for (int i = 0; token != NULL && i < 3; i++)
{
tokens[i] = token;
token = strtok(NULL, ",");
}
last_block_hash = tokens[0];
expected_hash_str = tokens[1];
hexStringToUint8Array(expected_hash_str, expected_hash, 20);
difficulty = tokens[2].toInt() * 100 + 1;
return true;
}
};
void setup() {
Serial.begin(500000);
Serial.println("\nDuino-Coin " + String(MINER_VER));
pinMode(LED_BUILTIN, OUTPUT);
#ifdef USE_MQTT
mqttClient.setServer(mqtt_server, mqtt_port);
#endif
#ifdef USE_DHT
Serial.println("Initializing DHT sensor");
dht.begin();
Serial.println("Test reading: " + String(dht.readHumidity()) + "% humidity");
Serial.println("Test reading: temperature " + String(dht.readTemperature()) + "*C");
#endif
// Autogenerate ID if required
chipID = String(ESP.getChipId(), HEX);
if(strcmp(RIG_IDENTIFIER, "Auto") == 0 ){
AutoRigName = "ESP8266-" + chipID;
AutoRigName.toUpperCase();
RIG_IDENTIFIER = AutoRigName.c_str();
}
SetupWifi();
SetupOTA();
lwdtFeed();
lwdTimer.attach_ms(LWD_TIMEOUT, lwdtcb);
if (USE_HIGHER_DIFF) START_DIFF = "ESP8266NH";
else START_DIFF = "ESP8266N";
if(WEB_DASHBOARD) {
if (!MDNS.begin(RIG_IDENTIFIER)) {
Serial.println("mDNS unavailable");
}
MDNS.addService("http", "tcp", 80);
Serial.print("Configured mDNS for dashboard on http://"
+ String(RIG_IDENTIFIER)
+ ".local (or http://"
+ WiFi.localIP().toString()
+ ")");
server.on("/", dashboard);
if (WEB_HASH_UPDATER) server.on("/hashrateread", hashupdater);
server.begin();
}
blink(BLINK_SETUP_COMPLETE);
}
void loop() {
br_sha1_context sha1_ctx, sha1_ctx_base;
uint8_t hashArray[20];
String duco_numeric_result_str;
// 1 minute watchdog
lwdtFeed();
// OTA handlers
VerifyWifi();
ArduinoOTA.handle();
if(WEB_DASHBOARD) server.handleClient();
ConnectToServer();
Serial.println("Asking for a new job for user: " + String(DUCO_USER));
#ifndef USE_DHT
client.print("JOB," +
String(DUCO_USER) + SEP_TOKEN +
String(START_DIFF) + SEP_TOKEN +
String(MINER_KEY) + END_TOKEN);
#endif
#ifdef USE_DHT
temp = dht.readTemperature();
hum = dht.readHumidity();
Serial.println("DHT readings: " + String(temp) + "*C, " + String(hum) + "%");
client.print("JOB," +
String(DUCO_USER) + SEP_TOKEN +
String(START_DIFF) + SEP_TOKEN +
String(MINER_KEY) + SEP_TOKEN +
String(temp) + "@" + String(hum) + END_TOKEN);
#endif
#ifdef USE_MQTT
if (!mqttClient.connected()) {
mqttReconnect();
}
mqttClient.loop();
#ifdef USE_DHT
long now = millis();
if (now - lastMsg > mqtt_update_time) {
lastMsg = now;
mqttClient.publish(temperature_topic, String(temp).c_str(), true);
mqttClient.publish(humidity_topic, String(hum).c_str(), true);
}
#endif
#endif
waitForClientData();
Serial.println("Received job with size of " + String(client_buffer));
MiningJob job;
job.parse((char*)client_buffer.c_str());
difficulty = job.difficulty;
Serial.println("Parsed job: " + job.last_block_hash + " " + job.expected_hash_str + " " + String(job.difficulty));
if (USE_HIGHER_DIFF) system_update_cpu_freq(160);
br_sha1_init(&sha1_ctx_base);
br_sha1_update(&sha1_ctx_base, job.last_block_hash.c_str(), job.last_block_hash.length());
float start_time = micros();
max_micros_elapsed(start_time, 0);
String result = "";
if (LED_BLINKING) digitalWrite(LED_BUILTIN, LOW);
for (unsigned int duco_numeric_result = 0; duco_numeric_result < job.difficulty; duco_numeric_result++) {
// Difficulty loop
sha1_ctx = sha1_ctx_base;
duco_numeric_result_str = String(duco_numeric_result);
br_sha1_update(&sha1_ctx, duco_numeric_result_str.c_str(), duco_numeric_result_str.length());
br_sha1_out(&sha1_ctx, hashArray);
if (memcmp(job.expected_hash, hashArray, 20) == 0) {
// If result is found
if (LED_BLINKING) digitalWrite(LED_BUILTIN, HIGH);
unsigned long elapsed_time = micros() - start_time;
float elapsed_time_s = elapsed_time * .000001f;
hashrate = duco_numeric_result / elapsed_time_s;
share_count++;
client.print(String(duco_numeric_result)
+ ","
+ String(hashrate)
+ ","
+ String(MINER_BANNER)
+ " "
+ String(MINER_VER)
+ ","
+ String(RIG_IDENTIFIER)
+ ",DUCOID"
+ String(chipID)
+ "\n");
waitForClientData();
Serial.println(client_buffer
+ " share #"
+ String(share_count)
+ " (" + String(duco_numeric_result) + ")"
+ " hashrate: "
+ String(hashrate / 1000, 2)
+ " kH/s ("
+ String(elapsed_time_s)
+ "s)");
break;
}
if (max_micros_elapsed(micros(), 500000)) {
handleSystemEvents();
}
}
}
Pastikan dulu pada bagian berikut ini telah diisi sesuai dengan aplikasi kita. Ganti bintang-bintang dengan isian yang benar.
// Change the part in brackets to your Duino-Coin username
const char *DUCO_USER = "**********"; //user dari duco wallet
// Change the part in brackets to your mining key (if you have enabled it in the wallet)
const char *MINER_KEY = "**********"; //mining key ( lihat di duco wallet)
// Change the part in brackets to your WiFi name
const char *SSID = "**********"; //nama wifi yang akan digunakan
// Change the part in brackets to your WiFi password
const char *PASSWORD = "**********"; //password wifinya
// Change the part in brackets if you want to set a custom miner name (use Auto to autogenerate, None for no name)
const char *RIG_IDENTIFIER = "**********"; //nama perangkat, harus beda tiap perangkat
Setelah program siap, pilih board pada Arduino IDE ke Generic ESP8266. Setelah board dipilih, silahkan compile dulu untuk mengecek apakah program sudah ok.
Sebelum upload program ke board, kita perlu memodif ESP-01 Programer adapter. Modul ESP-01 akan masuk ke mode download saat pin GPON 0 / FLASH dalam kondisi LOW. Untuk membuat kondisi seperti ini maka kita akan membuat konektor jumper antara pin GPIO 0 dengan pin GND. Saat jumper dipasang maka modul ESP 01 akan dalam mode download. Saat jumper dilepas maka kita dapat melakukan pemantauan data via serial monitor.
Modul ESP-01 Siap di program
Colokkan USB programmer nya ke laptop. pada arduino IDE, setting dulu COM port nya (terhubung ke Com berapa perangkatnya). Kalau udah siap semuanya maka gas kita tekan tombol upload. Tunggu proses upload program selesai, setelah selesai lepas programmer dari laptop, trus lepas jumper GPIO 0-GND, baru colokkan kembali programer ke USB laptop. Kita buka serial monitor, atur baudrate ke 500000. Apabila tidak ada kendala maka akan tampil data seperti berikut:
*lepas jumper untuk masuk ke mode aplikasi running (agar dapat diliat di serial monitor)
OK, module ESP01 siap digunakan untuk menambang. Silahkan upload program yang sama ke modul ESP yang lainnya dengan mengubah RIG Identifier nya terlebih dahulu. Setelah semua di program, maka RIG sudah siap dijalankan dan cuan cuan cuan (*sabar).
Gabung dalam percakapan