Ứng dụng: Khi thực hiện được việc điều khiển PWM ESP8266, chúng ta có thể ứng dụng trong rất nhiều dự án như điều khiển tốc độ động cơ qua internet, điều khiển động cơ servo qua internet, điều khiển độ sáng của bóng đèn,vv…
Các bước thực hiện :
Thực hiện tại phần server.
Trước hết chúng ta cần có một webserver chạy PHP (tham khảo bài viết trước)
Truy cập vào chương trình quản lý file của hosting, chúng ta tạo ra một số folder và file như sau.
+ Tạo folde js/ để chứa các thư viện như jquery, ajax,.. ( tôi sẽ để link download toàn bộ source cuối bài)
+ Tạo folder test/ để chứa file json. Tôi tạo ra sẵn file tuan.json trong folder này.
+ Tạo folder layout/ để chưa file header.php. Trong file này chúng ta sẽ thực hiện include các thư viện cần cho project.
Trong folder Tạo file header.php
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>CONTROL PWM ESP8266</title> <link rel="stylesheet" href="libs/style.css"> <link rel="stylesheet" href="libs/bootstrap/bootstrap.min.css"> <script src="js/jquery.min.js"></script> <script src="js/jquery.js"></script> <script src="js/bootstrap.min.js"></script> <script src="js/ajax.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script> |
Thực tế thì trong project này không cần dùng đến nhiều như vậy, sẽ sử dụng cho các project khác trong thời gian tới.
+ Tiếp theo, chúng ta tạo ra file pwm-control-esp8266.php. Trong file này chúng ta thực hiện viết chương trình tạo ra giao diện thanh trượt (slider) bằng javascript, cũng như là sử dụng ajax để có thể cập nhật ngay các giá trị mà người dùng thay đổi trong khi không cần reload lại toàn bộ trang web ( đây là một kĩ thuật rất hay để chúng ta áp dụng cho các ứng dụng IoT, về phần này luuvachiase.net sẽ có các bài viết ứng dụng ajax khác)
1 2 3 4 5 6 7 8 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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
<!DOCTYPE html> <html lang="en"> <head> <?php require "layout/header.php" ?> <style> /* Note: Try to remove the following lines to see the effect of CSS positioning */ .affix { bottom:1px; position:fixed; right:2px; z-index: 9999 !important; } .center { margin: auto; width: 60%; border: 3px solid #73AD21; padding: 10px; text-align: center; border: 3px solid green; } /* style for slider */ .slidecontainer { width: 50%; margin: auto; } .slider { -webkit-appearance: none; width: 100%; height: 25px; background: #d3d3d3; outline: none; opacity: 0.7; -webkit-transition: .2s; transition: opacity .2s; } .slider:hover { opacity: 1; } .slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 25px; height: 25px; background: #4CAF50; cursor: pointer; } .slider::-moz-range-thumb { width: 25px; height: 25px; background: #4CAF50; cursor: pointer; } </style> </head> <body> <h2 class="center" > COTROL PWM ESP8266 OVER INTERNET </h2> </div> <br> <div class="slidecontainer"> <input type="range" min="1" max="1023" value="0" class="slider" id="myRange"> <p>PWM ESP8266 Value: <span id="demo"></span></p> </div> <script> var slider = document.getElementById("myRange"); var output = document.getElementById("demo"); output.innerHTML = slider.value; slider.oninput = function() { output.innerHTML = this.value; id = $(this).val(); //alert (id); $.ajax({ url:"process.php", type:"post", data:"pwm="+id, async:true, success:function(kq){ // alert ("Sending PWM Value:"+id); } }); } </script> </body> </html> |
Giải thích ngắn gọn code:
- Phần từ <style> đến </style> chính là cách để chúng ta điều chỉnh các vấn đề liên quan đến giao diện như chiều dài thanh slider, màu sắc, căn giữa màn hình,vv… nói chung cái này các bạn cần có kiến thức về css và html.
- Trong <div> container có đoạn <input type=”range” min=”1″ max=”1023″ value=”0″ class=”slider” id=”myRange”> // phần này là cách chúng ta tạo ra các thanh slider, trong đó tham số cần chú ý đó là min=0, max=1023, chính là khoảng giá trị điều xung PWM cho ESP.
- Câu lệnh var output = document.getElementById(“demo”); // dùng để cập nhật giá trị thay đổi trên slider xuống dòng “PWM ESP8266 Value:”
- slider.oninput = function() {…}; // là function cho chúng ta biết được mỗi khi slider có sự thay đổi, và đây cũng là cái chúng ta cần để cập nhật giá trị điều chỉnh vào file tuan.json
- Bên trong function nói trên chính là đoạn code sau:
1 2 3 4 5 6 7 |
$.ajax({ url:"process.php", type:"post", data:"pwm="+id, async:true, success:function(kq { // alert ("Sending PWM Value:"+id); } |
Đoạn code trên sử dụng kĩ thuật AJAX có những đặc tính rất hay cho thiết kế các hệ thống IoT chạy trên web như:
- Update a web page without reloading the page ( cái này thích hợp cho giao diện điều khiển)
- Request data from a server – after the page has loaded
- Receive data from a server – after the page has loaded
- Send data to a server – in the background ( cái này là đặc tính chúng ta đang sử dụng)
url:”process.php”, // là dùng để gửi HTTP REQUEST đên địa chỉ là process.php
type:”post”, // kiểu REQUEST ở đây là POST, an toàn hơn GET
data:”pwm=”+id, // chính là dữ liệu gửi đi với name là pwm, và giá trị là id / Chúng ta sẽ gặp lại 2 biến này trong file process.php
async:true và success:function(kq { // alert (“Sending PWM Value:”+id); } //lần lượt là cách thức bất đồng bộ của AJAX và hàm trả về khi thực hiện thành công,
+ Tiếp theo, chúng ta tạo ra process.php, file xử lý chính cho việc thay đổi giá trị từ webserver xuống ESP8266.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php $jsonString = file_get_contents("test/tuan.json"); $data = json_decode($jsonString, true); if(isset($_POST["pwm"])) { $data_post = $_POST["pwm"]; $data['led1'] = $data_post; echo""; } // ################## Ghi gia trị vào file json ################################## $newJsonString = json_encode($data); file_put_contents("test/tuan.json", $newJsonString); ?> |
Giải thích ngắn gọn code:
Đầu tiên là nói về nhiệm vụ của process.php là thực hiện nhận REQUEST từ function đã giải thích ở trên, sau đó tách lấy giá trị id ( cũng chính là pwm_value ta muốn điều khiển). Giá trị tách được chúng ta sẽ thực hiện ghi vào file tuan.json trong folder test/
1 2 |
$jsonString = file_get_contents("test/tuan.json"); $data = json_decode($jsonString, true); |
2 câu lệnh trên có mục đích đọc file tuan.json sau đó decode ghi giá trị vào biến $data
1 2 3 4 5 6 |
if(isset($_POST["pwm"])) /* dùng câu lệnh này để kiểm tra $_POST["pwm"] có tồn tại hay ko, tránh báo lỗi biến php */ { $data_post = $_POST["pwm"]; $data['led1'] = $data_post; echo""; } |
Đoạn code trên thực hiện kiểm tra $_POST[“pwm”] có tồn tại hay ko, nếu có thì lấy giá trị của pwm trong POST REQUEST vào biến $data_post.
Sau đó gán giá trị biến $data_post vào led1 trong file tuan.json bằng câu lệnh:
$data[‘led1’] = $data_post;
Lập trình tại ESP8266
– PWM trên ESP8266
Có thể sử dụng từ PIN 0-16, trong bài này tôi sử dụng PIN16
Cách điều khiển PWM tương đối đơn giản, chúng ta chỉ cần dùng hàm
1 |
analogWrite(PIN,PWM_VALUE); |
+ Ở đây PIN là chân số của ESP
+ PWM_VALUE là giá trị mà chúng ta sẽ điều khiển độ rộng xung của ESP826, giá trị này chúng ta sẽ nhận từ server và nằm trong khoảng (0-1023)
– Lập trình ESP8266 giao tiếp với server và nhận giá trị điều khiển PWM
1 2 3 4 5 6 7 8 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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
// luuvachiase.net- ngoctuansqtt@gmail.com #include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> #include <WiFiClient.h> #include <ArduinoJson.h> //=========================NGƯỜI DÙNG TỰ ĐỊNH NGHĨA==========================// const char* ssid = "xxxx"; const char* password = "xxxxx"; const char* host = "your_host"; //luuvachiase.000webhostapp.com //=========================KHAI BÁO CÁC BIẾN TOÀN CỤC===========================// String path = "/test/tuan.json"; String line; const char* pwm; char tes; int count=0; bool json_ok =0,en=0; String tuan; String section="message"; unsigned long number; //====================================SETUP BAN ĐẦU, CHẠY 1 LẦN DUY NHẤT============// void setup() { WiFi.softAPdisconnect (true); // Tắt chức năng quảng bá SSID của AP. pinMode(2, OUTPUT); // Led bao trang thai ket noi server ok pinMode(10, OUTPUT); // Led bao trang thai ket noi wifi ok pinMode(12, OUTPUT); // chan dieu khien relay digitalWrite(2, HIGH); // Mức logic 1 là tắt led, logic 0 là sáng led digitalWrite(12, HIGH); digitalWrite(10, HIGH); Serial.begin(9600); delay(10); Serial.print("Connecting to Wifi: "); Serial.println(ssid); WiFi.begin(ssid, password); int wifi_ctr = 0; while (WiFi.status() != WL_CONNECTED) { digitalWrite(10, HIGH); delay(500); Serial.print("."); digitalWrite(10, LOW); delay(500); } Serial.println("Connected!"); } //====================================================================// void loop() { Serial.print("Connect to IoT-server"); Serial.println(host); WiFiClient client; const int httpPort = 80; if (!client.connect(host, httpPort)) { Serial.println("Connect to server fail!"); if(WiFi.status() != WL_CONNECTED) { digitalWrite(10, HIGH); // Nếu mất kết nối với wifi thì Led 10 sẽ tắt delay(500); Serial.print("."); digitalWrite(10, LOW); delay(300); } return; } digitalWrite(10, LOW); //ok Nếu kết nối với Server thành công LED 10 sẽ sáng while(1) { if(count==1) { Serial.print("No response:"); digitalWrite(2, HIGH); count=0; break; } // Nếu lần kết nối trước không thành công thì kết nối lại Serial.println("Send request"); client.print(String("GET ") + path + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: keep-alive\r\n\r\n"); digitalWrite(2, HIGH); delay(1000); // wait for server to respond count=1; //============================================= read response================================= while(client.available()){ count=2; // Serial.println("Data available!"); // chi để kiểm tra có nhận dc data ko digitalWrite(2, LOW); //ok //===================================== if(json_ok==false) { line = client.readStringUntil('\r'); //Serial.println(line); en=false; } else { line = client.readStringUntil('}'); int find_json = line.indexOf('{'); if(find_json<0) Serial.println("NOT JSON==>SKIP DATA"); else {tuan=line+"}"; en=true;Serial.println(tuan);} json_ok=false; } //======================================= if (line=="\n") { section="json"; json_ok=true; } else { section="header"; } //========================================= if(en==true) // Nếu response là json { String result = tuan.substring(1); line=""; // ===============Parse JSON=============== int size = result.length()+1; char json[size]; result.toCharArray(json, size); DynamicJsonBuffer jsonBuffer(size); JsonObject& json_parsed = jsonBuffer.parseObject(json); if (!json_parsed.success()) { Serial.println("parseObject() failed"); break; } else //============can read value============= pwm=json_parsed["led1"]; number = strtoul(pwm, NULL, 10); // chuyển từ const *char sang int analogWrite(16,number); // ghi giá trị pwm vào pin16 Serial.println(number); //=============end value================== }//end if(en==true) } // end while client_available }// while }// loop |
Đoạn code trên đã dùng cho nhiều project nên tôi không giải thích thêm nữa
Link tải toàn bộ mã nguồn
Demo cho điều khiển Servo
Trong các bài tiếp theo, chúng ta sẽ ứng dụng ajax và highchart để làm cho giao diện điều khiển trở nên mượt mà và chuyên nghiệp hơn, giao diện hiển thị dữ liệu ở dạng biểu đồ. Để cập nhật các bài viết của luuvachiase.net nhanh nhất, các bạn hãy nhập địa chỉ email của mình tại trang chủ ( như hình minh họa dưới đây) để nhận được thông báo ngay khi có bài viết mới. Thanks!
Comments 1