Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Osiloskop Web Arduino dengan Pemicu Canggih – 6 Saluran, Pengaturan Dapat Disesuaikan

Komponen dan Perlengkapan

Osiloskop Web Arduino dengan Pemicu Canggih – 6 Saluran, Pengaturan Dapat Disesuaikan
Arduino UNO
× 1
Osiloskop Web Arduino dengan Pemicu Canggih – 6 Saluran, Pengaturan Dapat Disesuaikan
PHPoC Shield untuk Arduino
× 1
Kabel Jumper
× 1

Tentang Proyek Ini

Jika Anda pemula, Anda dapat mempelajari lebih lanjut tentang Arduino - Wifi.

Demonstrasi

Fitur

Antarmuka Pengguna

Osiloskop Web Arduino dengan Pemicu Canggih – 6 Saluran, Pengaturan Dapat Disesuaikan

Cara Kerja

Karena Web Oscilloscope adalah modifikasi dari Web Serial Monitor pada PHPoC, saya akan menjelaskan cara kerja Web Serial Monitor terlebih dahulu.

PHPoC Shield memiliki aplikasi web bawaan yang disebut "Web Serial Monitor". Mirip dengan Serial Monitor di Arduino IDE. Perbedaannya dengan Serial Monitor di Arduino IDE adalah:

Secara detail, PHPoC Shield berkomunikasi dengan Arduino melalui SPI. Ketika pengguna mengakses Web Serial Monitor dari browser web. Setelah halaman dimuat, halaman membuat koneksi WebSocket ke PHPoC Shield. Saat ini, PHPoC Shield tumpuk pada Arduino, ia menangkap data dari pin TX Arduino, dan kemudian mengirim data ini ke Web Serial Monitor di browser web melalui WebSocket. Web Serial menerima data dan menampilkan di web.

Ini memungkinkan pengguna tidak hanya untuk melihat data di PC tetapi juga melihat data di ponsel atau perangkat apa pun yang mendukung browser web

Sekarang mari kita lihat cara kerja Web Oscilloscope.

Web Oscilloscope bekerja sama seperti Web Serial Monitor, kecuali bagian terakhirnya.

Alih-alih menampilkan data mentah di web, Web Oscilloscope memvisualisasikan data pada grafik. Fungsi lain ditambahkan, yang memungkinkan pengguna menyesuaikan UI dan melakukan pemicu.

Tentang data, yang dikirim dari Arduino

Arduino membaca data dari pin ADC (dari A0 hingga A5) dan membaca timestamp (dalam mikrodetik)

Data ADC dikonversi ke tegangan dan dicetak ke port serial bersama dengan timestamp menurut format berikut:

Catatan: Maksimum saluran adalah 6, tetapi Anda juga dapat mengirim hanya data satu, dua, atau tiga saluran.

Kode Sumber

Kode sumber mencakup dua bagian:

Cara Menggunakan

Osiloskop Web Arduino dengan Pemicu Canggih – 6 Saluran, Pengaturan Dapat Disesuaikan

Akses Web Oscilloscope dari browser web di PC atau ponsel pintar Anda dengan mengetik: https://ganti_dengan_ip/oscilloscope.php

Cara mengukur sinyal: Cukup gunakan dua kabel, satu ke GND dan satu ke pin Analog mana pun dari Arduino (A0 hingga A5). Hubungkan kedua pin ini ke titik yang ingin Anda periksa sinyalnya.

Karena ada 6 saluran, kita perlu 6 kabel ground. Untuk kenyamanan, Arduino hanya memiliki dua pin GND. Saya melakukan seperti di bawah ini untuk menambahkan lebih banyak pin GND.

Osiloskop Web Arduino dengan Pemicu Canggih – 6 Saluran, Pengaturan Dapat Disesuaikan

Kit Starter Arduino Terbaik untuk Pemula

Jika Anda mencari kit Arduino, lihat The Best Arduino Kit for Beginners


Referensi Fungsi

Kode

WebOscilloscope.inoArduino
Ini adalah kode Arduino. Kita TIDAK perlu mengirim semua data 6 saluran. Seperti yang Anda lihat, saya telah memberi komentar pada saluran data 3
#include <SPI.h> #include <Phpoc.h> #define AREF 5.0 #define ADC_MAX 1023.0 float ratio = AREF / ADC_MAX; void setup() { Serial.begin(115200); Phpoc.begin(); } void loop() { //read system time unsigned long time_a = micros(); // read the analog value and convert to voltage: float voltageChannel0 = analogRead(A0) * ratio; float voltageChannel1 = analogRead(A1) * ratio; float voltageChannel2 = analogRead(A2) * ratio; float voltageChannel3 = analogRead(A3) * ratio; float voltageChannel4 = analogRead(A4) * ratio; float voltageChannel5 = analogRead(A5) * ratio; // send system time first Serial.print(time_a); Serial.print(" "); // send value of each channel, seperated by " " or "\t". Serial.print(voltageChannel0); Serial.print(" "); Serial.print(voltageChannel1); Serial.print(" "); Serial.print(voltageChannel2); Serial.print(" "); //Serial.print(voltageChannel3); //Serial.print(" "); Serial.print(voltageChannel4); Serial.print(" "); //the last channel must send with new line charaters Serial.println(voltageChannel5); } 
oscilloscope.phpPHP
Ini adalah kode Web.
<!DOCTYPE html> <html> <head> <title>PHPoC Shield - Web Oscilloscope for Arduino</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body { text-align:center; background-color: #595959 ; color: white; display: flex; justify-content:space-between;} .graph_container {display:inline-block;} .setting_container {display:inline-block; float:right; background-color: #595959; padding: 0px; width: 260px;} .setting { justify-content: center; width: 260px; padding: 3px; display: flex; justify-content:space-between; } .button { background-color: #999999; border: none; color: white; padding: 5px; text-align: center; display: inline-block; font-weight: bold; font-size: 115%; } .button2, .select { border: none; padding: 5px; text-align: center; display: inline-block; font-weight: bold; font-size: 115%; } .select {width: 100%; background-color: #F2F2F2; color: #4CAF50;} .button_channel {border-radius: 50%; width: 14%;} .button_trigger {border-radius: 4px; width: 60%;} .button_go {border-radius: 4px; width: 35%;} .button_mode {border-radius: 8px; width: 32%;} .button_setting {border-radius: 45%; width: 33%;} .input_text {width: 50%; background-color: #F2F2F2; color: #4CAF50;} .label {width: 50%; background-color: transparent; color: #4CAF50;} button:focus{ outline: none; } #knob { padding: 5px; } </style> <script> var COLOR_BACKGROUND = "#404040"; var COLOR_TEXT = "#FFFFFF"; var COLOR_BOUND = "#FFFFFF"; var COLOR_GRIDLINE = "gray"; var COLOR_LINE = ["#33FFFF", "#FF00FF", "#FF0000", "#00FF00", "#FF8C00", "#666666"]; var LEGEND_WIDTH = 10; var X_AXIS_TITLE_HEIGHT = 40; var Y_AXIS_VALUE_WIDTH = 100; var PLOT_AREA_PADDING = 2; var X_GRIDLINE_NUM = 5; var Y_GRIDLINE_NUM = 7; var offset_y = [5, 10, 15, 20, 25, 30]; var voltage_div = [5, 5, 5, 5, 5, 5]; var time_div_ms = 1000; // ms var full_screen = false; var WSP_WIDTH; var WSP_HEIGHT; var X_AXIS_MIN_MS = 0; var X_AXIS_MAX_MS = time_div_ms * X_GRIDLINE_NUM; var Y_AXIS_MIN = 0; var Y_AXIS_MAX = 35; var PLOT_AREA_WIDTH; var PLOT_AREA_HEIGHT; var PLOT_AREA_PIVOT_X; var PLOT_AREA_PIVOT_Y; var knob_center_x; var knob_center_y; var knob_radius = 60; var knob_angle = 0; var knob_last_angle = 0; var knob_click_state = 0; var knob_mouse_xyra = {x:0, y:0, r:0.0, a:0.0}; var MIN_TOUCH_RADIUS = 20; var MAX_TOUCH_RADIUS = 60; var ws; var canvas; var knob; var ctx1; var ctx2; var buffer = ""; var live_data = []; var live_time_us = []; var trigger_data = []; var trigger_time_us = []; var BASE_TIME_MS; var DISPLAY_LIVE = 0; var DISPLAY_TRIGGER = 1; var TRIGGER_FALLING = 0; var TRIGGER_RISING = 1; var TRIGGER_BOTH = 2; var TRIGGER_STATE_IDLE = 0; var TRIGGER_STATE_RUN = 1; var TRIGGER_STATE_TRIGGERED = 2; var mode = "AUTO"; // no trigger var display_mode = DISPLAY_LIVE; var selected_channel = 0; var setting_option = "OFFSET"; var trigger_state = TRIGGER_STATE_IDLE; var trigger_type = TRIGGER_BOTH; var trigger_value = 1.5; var previous_state_value = 0; var stop_points = []; var trigger_count = 0; var time_diff_us = 0; var arduino_last_time_us = 0; var arduino_time_overflow_count = 0; function init() { canvas = document.getElementById("graph"); canvas.addEventListener("click", function(event){ full_screen = !full_screen; canvas_resize(); }); knob = document.getElementById("knob"); knob.addEventListener("touchstart", mouse_down); knob.addEventListener("touchend", mouse_up); knob.addEventListener("touchmove", mouse_move); knob.addEventListener("mousedown", mouse_down); knob.addEventListener("mouseup", mouse_up); knob.addEventListener("mousemove", mouse_move); var button_channel = document.getElementsByClassName("button_channel"); for(var i = 0; i < button_channel.length; i++) button_channel[i].addEventListener("click", function(event){ var channelId = parseInt(event.target.id); if(channelId < live_data.length) selected_channel = channelId; event.target.style.backgroundColor = "white"; }); document.getElementById("trigger_type").addEventListener("change", function(event){ trigger_type = parseInt(event.target.value);}); document.getElementById("GO").addEventListener("click", function(event){ if((mode == "SINGLE" && (trigger_state == TRIGGER_STATE_IDLE ||(trigger_state == TRIGGER_STATE_TRIGGERED && display_mode == DISPLAY_TRIGGER))) || mode == "NORMAL" && trigger_state == TRIGGER_STATE_IDLE) { trigger_state = TRIGGER_STATE_RUN; stop_points.splice(0, stop_points.length); event.target.style.backgroundColor = "white"; trigger_value = parseFloat(document.getElementById("trigger_value").value); var latest_value = live_data[selected_channel][live_data[selected_channel].length - 1]; previous_state_value = (latest_value - trigger_value) < 0 ? 0 : 1; } }); var button_mode = document.getElementsByClassName("button_mode"); for(var i = 0; i < button_mode.length; i++) button_mode[i].addEventListener("click", function(event){ if(mode != event.target.id) { trigger_state = TRIGGER_STATE_IDLE; trigger_count = 0; } mode = event.target.id; event.target.style.backgroundColor = "white"; }); var button_setting = document.getElementsByClassName("button_setting"); for(var i = 0; i < button_setting.length; i++) button_setting[i].addEventListener("click", function(event){ setting_option = event.target.id; event.target.style.backgroundColor = "white"; }); BASE_TIME_MS = (new Date()).getTime(); canvas_resize(); var ws_host_addr = ""; if((navigator.platform.indexOf("Win") != -1) && (ws_host_addr.charAt(0) == "[")) { ws_host_addr = ws_host_addr.replace(/[\[\]]/g, ''); ws_host_addr = ws_host_addr.replace(/:/g, "-"); ws_host_addr += ".ipv6-literal.net"; } ws = new WebSocket("ws://" + ws_host_addr + "/serial_monitor", "uint8.phpoc"); ws.onopen = ws_onopen; ws.onclose = ws_onclose; ws.onmessage = ws_onmessage; ws.binaryType = "arraybuffer"; } function ws_onopen() { ws.send("wsm_baud=115200\r\n"); } function ws_onclose() { alert("WebSocket was closed. Please reload page!"); ws.onopen = null; ws.onclose = null; ws.onmessage = null; ws = null; } function ws_onmessage(e_msg) { e_msg = e_msg || window.event; var u8view = new Uint8Array(e_msg.data); buffer += String.fromCharCode.apply(null, u8view); buffer = buffer.replace(/\r\n/g, "\n"); buffer = buffer.replace(/\r/g, "\n"); while(buffer.indexOf("\n") == 0) buffer = buffer.substr(1); if(buffer.lastIndexOf("\n") <= 0) return; var pos = buffer.lastIndexOf("\n"); var str = buffer.substr(0, pos); var new_sample_arr = str.split("\n"); buffer = buffer.substr(pos + 1); for(var si = 0; si < new_sample_arr.length; si++) { var str = new_sample_arr[si]; var arr = []; if(str.indexOf("\t") > 0) arr = str.split("\t"); else arr = str.split(" "); var time_us = parseInt(arr[0]); if(time_us < arduino_last_time_us) { arduino_time_overflow_count++; } arduino_last_time_us = time_us; time_us += arduino_time_overflow_count * 4294967295; var cur_time_ms = (new Date()).getTime() - BASE_TIME_MS; time_diff_us = cur_time_ms * 1000 - time_us; for(var id = 1; id < arr.length; id++) { var value = parseFloat(arr[id]); var i = id - 1; if(isNaN(value)) continue; if(i >= live_data.length) { live_data.push([value]); live_time_us.push([time_us]); } else { live_data[i].push(value); live_time_us[i].push(time_us); } if(i == selected_channel) handle_trigger(value); } if(live_data.length > 0) { for(var i = 0; i < live_data.length; i++) { if(live_data[i].length > 1) { while((time_us - live_time_us[i][0]) > (X_AXIS_MAX_MS * 1000)) { live_data[i].splice(0, 1); live_time_us[i].splice(0, 1); } } } } } } function handle_trigger(value) { if(value != trigger_value) { var current_state_value = (value - trigger_value) < 0 ? 0 : 1; if(current_state_value != previous_state_value) { var is_triggered = false; if(trigger_type == TRIGGER_BOTH) is_triggered = true; else if(trigger_type == TRIGGER_RISING && previous_state_value == 0) is_triggered = true; else if(trigger_type == TRIGGER_FALLING && previous_state_value == 1) is_triggered = true; previous_state_value = current_state_value; if(is_triggered) { if(trigger_state != TRIGGER_STATE_IDLE && (mode == "NORMAL" || (mode == "SINGLE" && trigger_state == TRIGGER_STATE_RUN))) { var cur_time_ms = (new Date()).getTime() - BASE_TIME_MS; var stop_time_ms = Math.round(cur_time_ms + X_AXIS_MAX_MS / 2); trigger_state = TRIGGER_STATE_TRIGGERED; stop_points.push({copied:false, stop_time_ms: stop_time_ms}); } } } } } function map(x, in_min, in_max, out_min, out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } function update_loop() { update_data(); update_view(); } function update_data() { var cur_time_ms = (new Date()).getTime() - BASE_TIME_MS; if(trigger_state == TRIGGER_STATE_TRIGGERED && stop_points.length > 0 && stop_points[0].stop_time_ms < cur_time_ms) { display_mode = DISPLAY_TRIGGER; if(!stop_points[0].copied) { trigger_data = JSON.parse(JSON.stringify(live_data)); trigger_time_us = JSON.parse(JSON.stringify(live_time_us)); stop_points[0].copied = true; trigger_count++; } if(stop_points.length > 1) { if(stop_points[1].stop_time_ms < cur_time_ms) { stop_points.splice(0, 1); } } } else { if(display_mode == DISPLAY_TRIGGER) { display_mode = DISPLAY_LIVE; trigger_data.splice(0, trigger_data.length); trigger_time_us.splice(0, trigger_time_us.length); } } } function update_view() { ctx1.clearRect(0, 0, WSP_WIDTH, WSP_HEIGHT); ctx1.save(); ctx1.translate(PLOT_AREA_PIVOT_X, PLOT_AREA_PIVOT_Y); ctx1.fillStyle = "black"; ctx1.fillRect(0, -PLOT_AREA_HEIGHT, PLOT_AREA_WIDTH, PLOT_AREA_HEIGHT); var time_div_text = time_div_ms.toFixed(2) + " ms / div"; ctx1.fillStyle = COLOR_TEXT; ctx1.textAlign = "center"; ctx1.fillText(time_div_text, PLOT_AREA_WIDTH / 2, X_AXIS_TITLE_HEIGHT / 2); draw_gridline(); draw_graph(); ctx1.restore(); draw_knob(knob_radius, knob_angle); update_button(); } function draw_gridline() { ctx1.strokeStyle = COLOR_GRIDLINE; ctx1.lineWidth = 1; for(var i = 0; i <= Y_GRIDLINE_NUM; i++) { var y_gridline_px = -map(i, 0, Y_GRIDLINE_NUM, 0, (PLOT_AREA_HEIGHT - 2 * PLOT_AREA_PADDING)); y_gridline_px = Math.round(y_gridline_px) - PLOT_AREA_PADDING + 0.5; ctx1.beginPath(); ctx1.moveTo(0, y_gridline_px); ctx1.lineTo(PLOT_AREA_WIDTH, y_gridline_px); ctx1.stroke(); } for(var i = 0; i <= X_GRIDLINE_NUM; i++) { var x_gridline_px = map(i, 0, X_GRIDLINE_NUM, 0, PLOT_AREA_WIDTH - 2 * PLOT_AREA_PADDING); x_gridline_px = Math.round(x_gridline_px) + PLOT_AREA_PADDING + 0.5; ctx1.beginPath(); ctx1.moveTo(x_gridline_px, 0); ctx1.lineTo(x_gridline_px, -PLOT_AREA_HEIGHT); ctx1.stroke(); } } function draw_graph() { var data_display; var time_display; if(display_mode == DISPLAY_LIVE) { data_display = live_data; time_display = live_time_us; } else { data_display = trigger_data; time_display = trigger_time_us; } var line_num = data_display.length; if(!line_num) return; var root_time_us; if(display_mode == DISPLAY_LIVE) root_time_us = ((new Date()).getTime() - BASE_TIME_MS) * 1000; else root_time_us = time_display[0][time_display[0].length - 1] + time_diff_us; ctx1.textAlign = "left"; ctx1.lineWidth = 2; for(var channel = 0; channel < line_num; channel++) { var sample_num = data_display[channel].length; if(sample_num >= 2) { var offset = -map(offset_y[channel], Y_AXIS_MIN, Y_AXIS_MAX, 0, PLOT_AREA_HEIGHT); ctx1.strokeStyle = COLOR_LINE[channel]; ctx1.fillStyle = COLOR_LINE[channel]; ctx1.fillText("CH" + channel + " " + voltage_div[channel].toFixed(1) + " v / div", -Y_AXIS_VALUE_WIDTH, offset); ctx1.beginPath(); for(var i = sample_num - 1; i >= 0; i--) { var sample_time_us = time_display[channel][i] + time_diff_us; var sample_value = data_display[channel][i]; x_value = sample_time_us - (root_time_us - (X_AXIS_MAX_MS * 1000)); if(x_value > 0) { y_value = map(sample_value, 0, 5, 0, voltage_div[channel]); y_value += offset_y[channel]; x_px = map(x_value, X_AXIS_MIN_MS * 1000, X_AXIS_MAX_MS * 1000, 0, PLOT_AREA_WIDTH); y_px = -map(y_value, Y_AXIS_MIN, Y_AXIS_MAX, 0, PLOT_AREA_HEIGHT) - PLOT_AREA_PADDING; if(i == sample_num - 1) ctx1.moveTo(x_px, y_px); else ctx1.lineTo(x_px, y_px); } } ctx1.stroke(); } } } function draw_knob(radius, angle) { ctx2.save(); ctx2.translate(knob_center_x, knob_center_y); ctx2.rotate(-angle * Math.PI / 180); var grd = ctx2.createLinearGradient(-radius, 0, radius, 0); grd.addColorStop(0, "#DC143C"); grd.addColorStop(0.1, "#DC143C"); grd.addColorStop(0.30, "#F5D6D6"); grd.addColorStop(0.47, "#DC143C"); grd.addColorStop(0.53, "#DC143C"); grd.addColorStop(0.70, "#F5D6D6"); grd.addColorStop(0.9, "#DC143C"); grd.addColorStop(1, "#DC143C"); ctx2.fillStyle = grd; ctx2.beginPath(); ctx2.arc(0, 0, radius, 0, 2 * Math.PI); ctx2.fill(); ctx2.fillStyle = "#DC143C"; ctx2.beginPath(); ctx2.arc(0, 0, radius / 4, 0, 2 * Math.PI); ctx2.fill(); ctx2.restore(); } function update_button() { var button_channel = document.getElementsByClassName("button_channel"); for(var i = 0; i < button_channel.length; i++) { if(button_channel[i].id == selected_channel) { button_channel[i].style.backgroundColor = COLOR_LINE[i]; button_channel[i].style.border = "3px solid " + COLOR_LINE[i]; } else { button_channel[i].style.backgroundColor = "#999999"; if(i < live_data.length) { button_channel[i].style.border = "3px solid " + COLOR_LINE[i]; } else { button_channel[i].style.border = "none"; } } } if((mode == "SINGLE" && (trigger_state == TRIGGER_STATE_IDLE ||(trigger_state == TRIGGER_STATE_TRIGGERED && display_mode == DISPLAY_TRIGGER))) || mode == "NORMAL" && trigger_state == TRIGGER_STATE_IDLE) document.getElementById("GO").style.backgroundColor = "#4CAF50"; else document.getElementById("GO").style.backgroundColor = "#999999"; if(trigger_state != TRIGGER_STATE_TRIGGERED) { document.getElementById("TRIGGER").style.backgroundColor = "#999999"; } else { document.getElementById("TRIGGER").style.backgroundColor = "#4CAF50"; } document.getElementById("TRIGGER").innerHTML = "TRIGGER (" + trigger_count + ")"; var button_mode = document.getElementsByClassName("button_mode"); for(var i = 0; i < button_mode.length; i++) { if(button_mode[i].id == mode) button_mode[i].style.backgroundColor = "#4CAF50"; else button_mode[i].style.backgroundColor = "#999999"; } var button_setting = document.getElementsByClassName("button_setting"); for(var i = 0; i < button_setting.length; i++) { if(button_setting[i].id == setting_option) button_setting[i].style.backgroundColor = "#DC143C"; else button_setting[i].style.backgroundColor = "#999999"; } } function check_update_xyra(event, knob_mouse_xyra) { var x, y, r, a; if(event.touches) { var touches = event.touches; x = (touches[0].pageX - touches[0].target.offsetLeft) - knob_center_x; y = knob_center_y - (touches[0].pageY - touches[0].target.offsetTop); } else { x = event.offsetX - knob_center_x; y = knob_center_y - event.offsetY; } r = Math.sqrt(x * x + y * y); a = Math.atan2(y, x); knob_mouse_xyra.x = x; knob_mouse_xyra.y = y; knob_mouse_xyra.r = r; knob_mouse_xyra.a = a; if((r >= MIN_TOUCH_RADIUS) && (r <= MAX_TOUCH_RADIUS)) return true; else return false; } function mouse_down() { event.preventDefault(); if(event.touches && (event.touches.length > 1)) knob_click_state = event.touches.length; if(knob_click_state > 1) return; if(check_update_xyra(event, knob_mouse_xyra)) { knob_click_state = 1; knob_last_angle = knob_mouse_xyra.a / Math.PI * 180.0; } } function mouse_up() { event.preventDefault(); knob_click_state = 0; } function mouse_move() { event.preventDefault(); var angle_pos, angle_offset; if(event.touches && (event.touches.length > 1)) knob_click_state = event.touches.length; if(knob_click_state != 1) return; if(!check_update_xyra(event, knob_mouse_xyra)) { knob_click_state = 0; return; } angle_pos = knob_mouse_xyra.a / Math.PI * 180.0; if(angle_pos < 0.0) angle_pos = angle_pos + 360.0; angle_offset = angle_pos - knob_last_angle; knob_last_angle = angle_pos; if(angle_offset > 180.0) angle_offset = -360.0 + angle_offset; else if(angle_offset < -180.0) angle_offset = 360 + angle_offset; knob_angle += angle_offset; if(setting_option == "TIME") { time_div_ms -= Math.round(angle_offset / 90 * time_div_ms); X_AXIS_MAX_MS = time_div_ms * X_GRIDLINE_NUM; } else if(setting_option == "VOLTAGE") { voltage_div[selected_channel] -= angle_offset / 90 * voltage_div[selected_channel]; } else if(setting_option == "OFFSET") { offset_y[selected_channel] -= angle_offset / 90 * 5; } } function canvas_resize() { canvas.width = 0; canvas.height = 0; var width = window.innerWidth - 20; var height = window.innerHeight - 20; if(full_screen) { document.getElementById("setting_container").style.display = "none"; WSP_WIDTH = width; WSP_HEIGHT = height; } else { if(height >= 1.5 * width) { document.getElementById("setting_container").style.display = "block"; WSP_WIDTH = width; } else { document.getElementById("setting_container").style.display = "inline-block"; WSP_WIDTH = width - document.getElementById('setting_container').offsetWidth; WSP_HEIGHT = height; } } canvas.width = WSP_WIDTH; canvas.height = WSP_HEIGHT; PLOT_AREA_WIDTH = WSP_WIDTH - Y_AXIS_VALUE_WIDTH; PLOT_AREA_HEIGHT = WSP_HEIGHT - X_AXIS_TITLE_HEIGHT; PLOT_AREA_PIVOT_X = Y_AXIS_VALUE_WIDTH; PLOT_AREA_PIVOT_Y = PLOT_AREA_HEIGHT; knob.width = 250 - 8 * 2; knob.height = 150 - 8 * 2; knob_center_x = Math.round(knob.width / 2 ); knob_center_y = Math.round(knob.height / 2); ctx1 = canvas.getContext("2d"); ctx2 = knob.getContext("2d"); ctx1.font = "14px Arial"; } setInterval(update_loop, 1000 / 60); window.onload = init; </script> </head> <body onresize="canvas_resize()"> <div class="graph_container" id="graph_container"> <canvas id="graph"></canvas> </div> <div class="setting_container" id="setting_container"> <div class="setting" id="setting_channel"> <button class="button button_channel" id="0">0</button> <button class="button button_channel" id="1">1</button> <button class="button button_channel" id="2">2</button> <button class="button button_channel" id="3">3</button> <button class="button button_channel" id="4">4</button> <button class="button button_channel" id="5">5</button> </div> <div class="setting"> <input type="text" class="button2 label" value="Trigger Value: " disabled> <input type="text" class="button2 input_text" id="trigger_value" value="1.5"> </div> <div class="setting"> <select class="select" id="trigger_type"> <option value="0">Falling</option> <option value="1">Rising</option> <option value="2" selected>Falling & Rising</option> </select> </div> <div class="setting" id="setting_trigger"> <button class="button button_trigger" id="TRIGGER" disabled>TRIGGER</button> <button class="button button_go" id="GO">GO</button> </div> <div class="setting" id="setting_mode"> <button class="button button_mode" id="AUTO">AUTO</button> <button class="button button_mode" id="NORMAL">NORMAL</button> <button class="button button_mode" id="SINGLE">SINGLE</button> </div> <canvas id="knob"></canvas> <div class="setting" id="setting_option"> <button class="button button_setting" id="TIME">ms / div</button><br> <button class="button button_setting" id="VOLTAGE">V / div</button><br> <button class="button button_setting" id="OFFSET">Offset</button><br> </div> </div> </body> </html> 

Skematik

Osiloskop Web Arduino dengan Pemicu Canggih – 6 Saluran, Pengaturan Dapat Disesuaikan

Proses manufaktur

  1. Sistem Pencahayaan DMX Dikonrol Web – Kontroler Master Arduino
  2. Membuat Osiloskop Arduino 20 kHz pada Layar LCD Nokia 5110 – Panduan DIY Mudah
  3. Membuat Spybot Arduino yang Dikontrol melalui Bluetooth
  4. FlickMote: Remote IR Kendali Gestur untuk Rumah Cerdas
  5. DIY Arduino TV B-Gone: Remote Universal untuk Semua TV
  6. Bangun Jam Master LED Kustom dengan Alarm – Terlihat dari Jarak 12 Meter
  7. Find Me: Pelacak Item Cerdas dengan Arduino dan Bluetooth
  8. Solusi Daya Teroptimasi untuk Proyek Arduino
  9. Tic Tac Toe Arduino dengan Matriks LED MAX7219 dan Kotak Kardus
  10. Membuat Robot Quadruped Arduino Cerdas: Panduan Langkah demi Langkah