Click here to Skip to main content
15,885,914 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Help: the problem of realizing serial communication using Web Serial API. Every 1000ms, my sensor will send a piece of data with a format similar to "CH1CH2CH3: 2.408130 2.456470 13152-1552 9440", and I need to obtain two groups of decimals represented by CH1 and CH2, that is, the first two decimals are assigned values for V1 and V2 respectively, and the subsequent calculations are also based on this. Now I can receive data after opening the serial port connection, but V1 and V2 are displayed as "NAN", that is, null values, and the console shows that I have successfully received the data. I suspect that there is something wrong with my data analysis, but I can't solve it at present. Do any bosses know how to modify my code?

What I have tried:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>针灸数据采集</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="icon" type="image/x-icon" href="data:image/png;base64,iVBORw0KGgo=">
    <meta charset="utf-8" />
</head>
<body>
    <canvas id="myChart" height="60px"></canvas>
    <div>
        <button id="butConnect">打开连接</button>
        <span style="padding: 1%"></span>
        <button id="butEnd">关闭连接</button>
        <span style="padding: 1%"></span>
        <button id="butClearData">清空接收数据</button>
    </div>
    <div style="margin: 10px">
        <label for="ch1-average">前端电压平均值:</label>
        <input type="text" id="ch1-average" readonly />
        <label for="ch2-average">后端电压平均值:</label>
        <input type="text" id="ch2-average" readonly />
        <label for="ch1-variance">前端电压方差:</label>
        <input type="text" id="ch1-variance" readonly />
        <label for="ch2-variance">后端电压方差:</label>
        <input type="text" id="ch2-variance" readonly />
    </div>

    <div style="margin: 10px">接收数据:</div>
    <div id="received-data-list" style="border: groove; margin: 10px"></div>

    <script>
var ctx = document.getElementById("myChart").getContext("2d");
var chart = new Chart(ctx, {
    type: "line",
    data: {
        labels: [],
        datasets: [
            {
                label: "前端薄膜电压",
                borderColor: "rgb(255, 99, 132)",
                data: [],
                fill: false,
            },
            {
                label: "后端薄膜电压",
                borderColor: "blue",
                data: [],
                fill: false,
            },
        ],
    },
    options: {
        title: {
            display: true,
            text: new Date().toLocaleDateString(),
        },
    },
});

const dataList = document.getElementById("received-data-list");
let keepReading = true;
let reader;
let writer;
let receivedBytes = new Uint8Array();
const frameLength = 43; // 定义每帧数据的长度
const dataArr = [];

document.getElementById("butConnect").addEventListener("click", async () => {
    try {
        const port = await navigator.serial.requestPort();
        await port.open({ baudRate: 9600 });
        keepReading = true;
        reader = port.readable.getReader();
        writer = port.writable.getWriter();
        console.log("Port opened successfully");

        // 清除之前的数据
        receivedBytes = new Uint8Array();
        dataList.innerHTML = "";
        chart.data.labels = [];
        chart.data.datasets[0].data = [];
        chart.data.datasets[1].data = [];
        chart.update();
        console.log("All data cleared");

        const writeInt = setInterval(async () => {
            await writer.ready;
            const commandframe = new TextEncoder().encode("read_data");
            await writer.write(commandframe);
            console.log("Command frame written");
        }, 1000);

        while (port.readable && keepReading) {
            try {
                const { value, done } = await reader.read();
                if (done) {
                    reader.releaseLock();
                    writer.releaseLock();
                    break;
                }
                if (value) {
                    receivedBytes = concatBytes(receivedBytes, value);
                    if (receivedBytes.length >= frameLength) {
                        const receivedData = new TextDecoder().decode(receivedBytes);
                        console.log(`Received data: ${receivedData}`);
                        let parsedData = receivedData.match(/^CH[1-3]\s(CH1\s+([\d\.]+)\s+)?(CH2\s+([\d\.]+)\s+)?(CH3\s+([\d\.]+)\s+)?/);
                        if (parsedData) {
                            let V1 = parseFloat(parsedData[2]);
                            let V2 = parseFloat(parsedData[4]);
                            let datatime = new Date();
                            let frame = {
                                datatime,
                                V1,
                                V2,
                            };
                            console.log(`Valid data: ${frame}`);
                        
                            // 存储到 dataArr 数组中
                            dataArr.push(frame);
                            dataList.innerHTML += `<p>[${datatime.toLocaleString()}] -> V1: ${V1}, V2: ${V2}</p>`;
                            chart.data.labels.push(datatime.toLocaleTimeString());
                            chart.data.datasets[0].data.push(frame.V1);
                            chart.data.datasets[1].data.push(frame.V2);
                            chart.update();
                            console.log("Chart updated");
                        }
                        receivedBytes = new Uint8Array();
                    }
                }
            } catch (error) {
                console.error(error);
            } finally {
                console.log("Reading loop finished");
            }
        }
        clearInterval(writeInt);
        await port.close();
        console.log("Port closed");
    } catch (error) {
        console.error(error);
    }
});

document.getElementById("butEnd").addEventListener("click", async () => {
    keepReading = false;
    reader.cancel();
    const jsonHandle = await window.showSaveFilePicker();
    const writableStream = await jsonHandle.createWritable();
    const aBlob = new Blob([JSON.stringify(dataArr)], {
        type: "text/plain",
    });
    await writableStream.write(aBlob);
    receivedBytes = new Uint8Array();
    await writableStream.close();
    console.log("Data saved to file");

    // 根据时间戳筛选出数据
    let filteredArr = dataArr.filter((item) => item.datatime >= openTimestamp);
    let ch1Arr = filteredArr.map((item) => item.V1);
    let ch2Arr = filteredArr.map((item) => item.V2);
    // 计算平均值和方差
    let ch1Avg = ch1Arr.reduce((acc, val) => acc + val, 0) / ch1Arr.length;
    let ch2Avg = ch2Arr.reduce((acc, val) => acc + val, 0) / ch2Arr.length;
    let ch1Variance = ch1Arr.reduce((acc, val) => acc + (val - ch1Avg) ** 2, 0) / ch1Arr.length;
    let ch2Variance = ch2Arr.reduce((acc, val) => acc + (val - ch2Avg) ** 2, 0) / ch2Arr.length;
    // 显示平均值和方差
    document.getElementById("ch1-average").value = ch1Avg.toFixed(6);
    document.getElementById("ch2-average").value = ch2Avg.toFixed(6);
    document.getElementById("ch1-variance").value = ch1Variance.toFixed(6);
    document.getElementById("ch2-variance").value = ch2Variance.toFixed(6);
    console.log("Data analysis completed and results displayed");
});

document.getElementById("butClearData").addEventListener("click", () => {
    receivedBytes = new Uint8Array();
    dataList.innerHTML = "";
    chart.data.labels = [];
    chart.data.datasets[0].data = [];
    chart.data.datasets[1].data = [];
    chart.update();
    console.log("All data cleared");
});

function concatBytes(uint8a, uint8b) {
    let tmp = new Uint8Array(uint8a.length + uint8b.length);
    tmp.set(uint8a, 0);
    tmp.set(uint8b, uint8a.length);
    return tmp;
}


    </script>

</body>
</html>
Posted
Updated 21-May-23 1:55am
v2

1 solution

The value NAN tells you that the variable(s) does not contain a valid number, and the issue is with the two lines:
JavaScript
let V1 = parseFloat(parsedData[2]);
let V2 = parseFloat(parsedData[4]);

So you need to use the debugger to see what is in the two fields at parsedData[2] and parsedData[4]. Whatever they contain the calls to parseFloat are not returning valid floating point values.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900