Osiloskop Web Arduino dengan Pemicu Canggih – 6 Saluran, Pengaturan Dapat Disesuaikan
Komponen dan Perlengkapan
×
1
PHPoC Shield untuk Arduino
×
1
×
1
Tentang Proyek Ini
Jika Anda pemula, Anda dapat mempelajari lebih lanjut tentang Arduino - Wifi.
Demonstrasi
Fitur
Mendukung 6 saluran Mendukung pemicu tunggal, beberapa pemicu Mode pemicu dapat dipilih: jatuh, naik, jatuh, dan naik Nilai pemicu dapat diatur Menyesuaikan pembagian waktu melalui knob web Menyesuaikan pembagian tegangan untuk setiap saluran melalui knob web Menyesuaikan offset tampilan untuk setiap saluran melalui knob web Ketuk atau Klik untuk menyembunyikan/melihat area pengaturan Bekerja lintas platform: Window, Linux, iOS, Android... (karena karakteristik web), yang memiliki browser web
Antarmuka Pengguna
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:
Serial Monitor di Arduino IDE: Membaca data dari pin tx arduino melalui kabel USB.Web Serial Monitor pada PHPoC Shield: Membaca data dari pin tx arduino melalui Internet
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:
Pertama, timestamp, diikuti oleh spasi atau karakter "\t". Dan kemudian, diikuti oleh data tegangan. data setiap saluran dipisahkan oleh spasi atau karakter "\t". Akhirnya karakter newline
Catatan: Maksimum saluran adalah 6, tetapi Anda juga dapat mengirim hanya data satu, dua, atau tiga saluran.
Kode Sumber
Kode sumber mencakup dua bagian:
Kode Arduino (lihat WebOscilloscope.ino) Kode aplikasi web (oscilloscope.php): ini adalah kode antarmuka pengguna. Ini perlu diunggah ke PHPoC Shield sesuai dengan instruksi ini
Cara Menggunakan
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.
Kit Starter Arduino Terbaik untuk Pemula
Jika Anda mencari kit Arduino, lihat The Best Arduino Kit for Beginners
Referensi Fungsi
Serial.begin() Serial.println() delay() millis() for loop while loop if else loop() setup() String.toInt() String.substring() String.indexOf() String.remove() String.equals()
Kode
WebOscilloscope.ino oscilloscope.php
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