Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 100 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
100
Dung lượng
3,16 MB
Nội dung
BỘ GIÁO DỤC VÀ ĐÀO TẠO TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI - ĐOÀN MẠNH CƯỜNG NGHIÊNCỨUTHIẾTKẾHỆTHỐNGTHEODÕINHỊPTIMBẰNGARDUINOUNOVÀPROCESSING LUẬN VĂN THẠC SĨ KỸ THUẬT KỸ THUẬT Y SINH Hà nội - 2016 BỘ GIÁO DỤC VÀ ĐÀO TẠO TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI ĐOÀN MẠNH CƯỜNG NGHIÊNCỨUTHIẾTKẾHỆTHỐNGTHEODÕINHỊPTIMBẰNGARDUINOUNOVÀPROCESSING Chuyên ngành: Kỹ thuật y sinh LUẬN VĂN THẠC SĨ KỸ THUẬT KỸ THUẬT Y SINH NGƯỜI HƯỚNG DẪN KHOA HỌC: TS VŨ DUY HẢI Hà nội - 2016 LỜI CAM ĐOAN Tôi xin cam đoan viết hoàn toàn thống không chép, kết đo đạc mô phỏng có luận văn chưa từng đươ ̣c công bố từ tài liệu hình thức Các thông tin sử du ̣ng luận văn có nguồn gố c đươ ̣c trić h dẫn rõ ràng Tôi xin hoàn toàn chịu trách nhiệm có dấu hiệu chép kết từ các tài liệu khác LỜI CẢM ƠN Trong thời gian học tâ ̣p, nghiên cứu hoàn thiê ̣n luâ ̣n văn, em đã nhâ ̣n đươ ̣c sự giúp đỡ rấ t tâ ̣n tình chu đáo của các thầy cô giáo viện Điê ̣n tử – Viễn thông Trường Đa ̣i ho ̣c bách khoa Hà Nô ̣i Đầ u tiên em xin gửi lời cảm ơn sâu sắ c tới TS Vũ Duy Hải, người đã tâ ̣n tiǹ h hướng dẫn và giúp đỡ em hoàn thành luâ ̣n văn tố t nghiê ̣p tha ̣c sỹ suố t thời gian vừa qua Em cũng xin cảm ơn các quý thầ y cô, các anh chi ̣và các ba ̣n ta ̣i viện Điê ̣n tử - Viễn thông, Đa ̣i học Bách khoa Hà Nội đã có những góp ý kiến kip̣ thời và bổ ić h, giúp đỡ em suố t quá trình nghiêncứu luâ ̣n văn này Ngoài ra, em xin bày tỏ lòng biế t ơn sâu sắc đế n gia đin ̀ h, ba ̣n bè, người đã ủng hô ̣ em suố t quá triǹ h ho ̣c tâ ̣p và hoàn thành chương trin ̀ h đào ta ̣o Thạc sỹ ta ̣i viện Điê ̣n tử – Viễn thông, Đa ̣i học Bách khoa Hà nội Mặc dù em đã nỗ lực và cố gắ ng hoàn thiê ̣n luâ ̣n văn bằ ng tấ t cả nhiê ̣t tin ̀ h và lực của mình, nhiên không thể tránh khỏi những thiế u sót, rấ t mong nhâ ̣n đươ ̣c những đóng góp quý báu của quý thầ y cô và các ba ̣n Em xin chân thành cảm ơn Hà Nội, ngày 21 tháng 10 năm 2016 HỌC VIÊN ĐOÀN MẠNH CƯỜNG DANH MỤC CÁC TỪ VIẾT TẮT THUẬT NGỮ DỊCH NGHĨA VIẾT TẮT TIẾNG ANH PPG PhotoPlethysmoGram Đồ thị đo thể tích quang học HR Heart Rate Nhịptim BPM Beats Per Minute Số nhịp mỗi phút IBI Inter Beat Interval HRV Heart Rate Variability Sự biến thiên nhịptim PTT Pulse Transit Time Thời gian truyền xung PSD Power Spectral Density Mật độ phổ lượng PTT Pulse Transit Time Thời gian truyền xung ECG ElectroCardioGram Điện tâm đồ FFT Fast Fourier Transform Biến đổi nhanh Fourier HF High Frequency Tần số cao LF Low Frequency Tần số thấp VLF Very Low Frequence Tần số thấp Khoảng thời gian hai nhịptim liên tiếp MỤC LỤC LỜI CAM ĐOAN LỜI CẢM ƠN DANH MỤC CÁC TỪ VIẾT TẮT MỤC LỤC DANH MỤC HÌNH ẢNH LỜI MỞ ĐẦU Chương TỔNG QUAN VỀ ĐỀ TÀI 10 1.1 Giới thiệu chung nhịptim 10 1.2 Phân biệt nhịptim với số huyết áp 13 1.3 Nhịptim trung bình 14 1.4 Một số phương pháp xác định nhịptim 16 1.4.1 Sóng mạch, nhịp mạch phương pháp đo nhịptim thủ công 16 1.4.2 Xác định nhịptim mục tiêu để luyện tập an toàn 17 1.4.3 Phương pháp xác định nhịptim y tế 19 14.3.1 Nghe tim 19 1.4.3.2 Phương pháp đo nhịptim Oscillometric 19 1.4.3.3 Điện tâm đồ (ECG) 21 1.4.4 Đo nhịptim các thiết bị điện tử 22 1.4.5 Xác định nhịptim phương pháp hấp thụ quang học 24 1.5 Sự quan trọng của nhịptim 25 1.6 Kết luận chương 26 Chương CƠ SỞ THU NHẬN TÍN HIỆU ĐIỆN TIM 27 2.1 Cấu trúc hoạt động của trái tim người 27 2.2 Điện sinh lý tim 30 2.3 Mô hình phân tách phức hợp QRS của Pan, Hamilton Tompkins 36 2.4 Đồ thị đo thể tích quang học - Photoplethysmogram (PPG) 42 2.4.1 Khái niệm 42 2.4.2 Dạng tín hiệu PPG 43 2.4.3 Kỹ thuật thu PPG 43 2.5 Sự biến thiên của nhịptim (HRV - Heart Rate Variability) 44 2.5.1 Phân tích HRV miền thời gian 45 2.5.2 Phân tích HRV miền tần số 47 2.6 Kết luận chương 52 Chương PHÂN TÍCH CƠ SỞ THIẾTKẾ MODULE ĐO 53 VÀ GIÁM SÁT NHỊPTIM 53 3.1 Yêu cầu đề tài 53 3.2 Sơ đồ khối hệthống 53 3.3 Lựa chọn linh kiện 58 3.3.1 Cảm biến nhịptim Pulse SenSor 58 3.3.2 ArduinoUno R3 59 3.4 Kết luận chương 64 Chương THỰC THI THIẾTKẾ 66 MODULE ĐO VÀ GIÁM SÁT NHỊPTIM 66 4.1 Thiếtkế phần cứng 66 4.2 Thiếtkế phần mềm 67 4.3 Kết nghiêncứu 69 4.5 Kết luận chương 72 KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN 74 TÀI LIỆU THAM KHẢO 75 PHỤ LỤC 75 DANH MỤC HÌNH ẢNH Hình 1.1 Thông số đánh giá nhịp người bình thường trạng thái nghỉ ngơi 15 Hình 1.2 Các điểm động mạch áp sát bề mặt da 16 Hình 1.3 Một thiết bị nghe nhịptim 19 Hình 1.5 Nguyên tắc đo nhịptim phương pháp Ocillometric 20 Hình 1.6 Điện tâm đồ 21 Hình 1.7 Răng cưa điện tâm đồ 22 Hình 1.8 Một loại vòng đeo tay đồng hồ thông minh có chức đo nhịptim 23 Hình 1.9 Đo nhịptim ứng dụng cảm biến nhịptim SmartPhone 23 Hình 1.10 Thiết bị đo huyết áp, nhịp tim, SpO2 điện tử loại quấn tay kẹp tay 23 Hình 1.11 Dạng tín hiệu nhịptim 24 Hình 1.12 Sự hấp thụ ánh sáng động mạch truyền qua ngón tay 25 Hình 2.1 Buồng tim van tim 27 Hình 2.2 Hệthống dẫn truyền tim 29 Hình 2.3 Sơ đồ thu nhận tín hiệu điện tim với điểm đo 31 Hình 2.4 Hệthống dẫn truyền điện hoạt đồng vị trí tim 32 Hình 2.5 Các đạo trình chi Einthoven tam giác Einthoven 33 Hình 2.6 Các thành phần sóng điện tim cần phân tích 34 Hình 2.7 Các đặc trưng tần số tín hiệu điện tim 35 Hình 2.8 Phương pháp phân tách phức hợp QRS Pan Tompkin 36 Hình 2.9 Mô hình thực phân tách phức hợp QRS Hamilton Tompkins 37 Hình 2.10 Mối liên hệ việc di chuyển cửa sổ phức hợp QRS 39 Hình 2.11 Dạng tín hiệu PPG 43 Hình 2.12 Thu tín hiệu PPG sử dụng LED PD (Photodetector) 44 Hình 2.13 Phát đỉnh với cửa sổ 11 46 Hình 2.14 Xác định đỉnh tín hiệu 46 Hình 2.15 Khoảng cách đỉnh liên tiếp dạng tín hiệu HRV 47 Hình 2.16 Mật độ phổ lượng miền VLF, LF HF 50 Hình 2.17 Cân hệ thần kinh tự chủ biến thiên nhịptim 51 Hình 2.18 Hình Mật độ phổ lượng miền tần số LF HF 52 Hình 3.1 Sơ đồ khối hệthống 53 Hình 3.2 Sơ đồ mạch cảm biến dựa cảm biến xung Pulse 54 Hình 3.3 Sự truyền ánh sáng qua động mạch 55 Hình 3.4 Đồ thị hấp thụ ánh sáng sau truyền qua động mạch 57 Hình 3.5 Sự thay đổi cường độ sáng truyền qua ngón tay 57 Hình 3.6 Cảm biến nhịptim (xung) Pulse Sensor 58 Hình 3.7 Sơ đồ nguyên lý cảm biến nhịptim 59 Hình 3.8 Board mạch phát triển ArduinoUno R3 61 Hình 3.7 ArduinoUno R3 Pinout 65 Hình 4.1 Hình ảnh phần cứng kết nối với máy tính 66 Hình 4.2 Lưu đồ thuật toán chương trình điều khiển 67 Hình 4.3 Dạng sóng nhịptim 68 Hình 4.4 Hình ảnh hiển thị giao diện phần mềm Processing 69 Hình 4.5 Xung tín hiệu điện tim thu 70 Hình 4.6 Các giá trị dạng phổ lượng BPM, IBI, tần số HR 71 Hình 4.7 Các giá trị phổ lượng IBI Spectrum, LF, HF, Beats LF vs HF Percentage 71 LỜI MỞ ĐẦU Trái tim thành phần quan trọng thể người Quá trình hoạt động ổn định của tim giúp cho thể khoẻ mạnh trì sự sống Biểu của tim có thể cho phép xác định các trạng thái bệnh tật của người Quá trình phân tích tín hiệu điện tim có thể xác định khá xác các biểu thường gặp của bệnh tim từ đưa các nhận định tình trạng sức khoẻ của bệnh nhân Thế kỷ 20 coi kỷ nguyên của các bệnh tim mạch, kỷ 21 nay, bệnh tim mạch, song song với các bệnh ung thư tiểu đường, nằm số bệnh phổ biến nguy hiểm cho người Bệnh tim mạch đặc biệt nguy hiểm không xảy đơn độc mà nguyên nhân của nhiều bệnh tim mạch không tim mạch khác, chữa trị khó khăn hậu để lại lớn Chính vậy, câu nói “phòng bệnh chữa bệnh” lại có ý nghĩa kinh tế ngày phát triển vũ bão, môi trường ngày trở lên ô nhiễm Vấn đề theodõi sức khỏe thường xuyên trở lên cấp thiết việc giám sát nhịptim đặt lên hàng đầu cho người Để đo nhịp tim, thay cho phương pháp cảm biến áp suất phương pháp để lấy tín hiệu đồng với nhịptim mà không ảnh hưởng tới sự lưu thông máu nơi cảm biến nâng cao độ xác cho phép đo Đề tài đề xuất phương pháp đo nhịptim phương pháp không xâm lấn, có nghĩa không tác động đến thể bệnh nhân, nhằm giúp người có thể xác định nhịptim của để có thể đánh giá chung tình hình sức khỏe của thân, đồng thời có kế hoạch khám bệnh điều trị cho phù hợp Nội dung của Luận văn “Nghiên cứu, thiếtkếhệthốngtheodõinhịptimArduino Processing” gồm các phần sau: Chương Tổng quan đề tài Chương Cơ sở thu nhận tín hiệu điện tim Chương Phân tích sở thiếtkế Module đo giám sát nhịptim Chương Thực thi thiếtkế Module đo giám sát nhịptim ///////////////////////////////////////////////////////////////////// void setup() { surface.setResizable(false); // don't allow window to be resized size(1390, 760); myPort = new Serial(this, comPort, 115200); // don't generate a serialEvent() unless you get a newline character: myPort.bufferUntil('\n'); PPG = new int[maxDots]; prints heartbeat waveform for (int i=0; i 220) // keeps line from drawing into title box BPMtemp = 220; line(BPMxPos, 229, BPMxPos, 230-BPMtemp); // left to right+1; if (BPMxPos == BPMWindowWidth+BPMWindowY) // reset BPM at window end { stroke(0); fill(0); rect(BPMWindowY-1, 30, BPMWindowWidth+1, BPMWindowHeight+1, 5); // bpm window BPMxPos = BPMWindowY+1; } //reset stroke(0); fill(0); textSize(LabelSize); text("BPM: "+ BPM, BPMWindowY + 10, 0, width, height); text("IBI: " + IBI, IBIWindowY + 10, 0, width, height); text("LF vs HF Power", HLWindowY + 20, 0, width, height); if (freq > 2) // don't let he dot plot go out of graph bounds freq = 0; String F = nf(freq, 1, 3); printing // format the freq variable for text("Hz: " + F, FreqWindowY+10, 0, width, height); fill(255); // draw Beat Counter window rect(DataWindowY, 0, DataWindowWidth, DataWindowHeight, 5); rect(DataWindowY, 0, DataWindowWidth, 30, 5); fill(0); text("Beats: " + beatCount, DataWindowY+10, 0, width, height); float hPercent = 100; float lPercent = 100; String lf = ""; String hf = ""; if (LF > && HF > 0) { 88 lf = nf((float)(LF), 1, 1); hf = nf((float)(HF), 1, 1); hPercent = 100-(HF/(HF+LF)*100); lPercent = 100-(LF/(HF+LF)*100); } // draw out session averages for HF and LF fill(255); rect(HLSessionWindowY-1, 100, HLSessionWindowWidth+1, HLSessionWindowHeight+30, 5); // HLSession window fill(0); textSize(13); text("LF vs HF Percentage ", DataWindowY+15, 105, width, height); fill(LFcolor); rect(HLSessionWindowY-1, 130 + lPercent, HLSessionWindowWidth/2, HLSessionWindowHeight - lPercent, 5); // HLSession window fill(HFcolor); rect(HLSessionWindowY+(HLSessionWindowWidth/2), 130 + hPercent, HLSessionWindowWidth/2, HLSessionWindowHeight- hPercent, 5); // HLSession window fill(0); textSize(14); text("(LF 15) = " + hf, DataWindowY+5, 70, width, height); textSize(12); text("%" + nf(100-lPercent, 1, 1), HLSessionWindowY+20, 125 + lPercent, HLSessionWindowWidth/2); text("%" + nf(100-hPercent, 1, 1), HLSessionWindowY+(HLSessionWindowWidth/2)+20, 125 + hPercent, HLSessionWindowWidth/2); if (beatCount < 10) { rect(HLWindowY-1, 30, HLWindowWidth+1, HLWindowHeight+1, 5); fill(255, 0, 0); textSize(14); text("Gathering Data", HLxPos+40, 60); text(10-beatCount, HLxPos+82, 80); } else { if (firstTime) rect(HLWindowY-1, 30, HLWindowWidth+1, HLWindowHeight+1, 5); } //draw LF vs HF chart // LF = 1000; // used to test scaling //HF = 1500; // // used to test scaling float mappedLF = 230 - map((float)LF, 0, 2000, 0, 200); float mappedLFold= 230 - map((float)LFold, 0, 2000, 0, 200); float mappedHF = 230 - map((float)HF, 0, 2000, 0, 200); float mappedHFold = 230 - map((float)HFold, 0, 2000, 0, 200); 89 if (pulseData) { stroke(LFcolor); strokeWeight(1.1); line(HLxPos-LFHFmagnify, mappedLFold, (HLxPos+1), mappedLF); // left to right LF line graph stroke(HFcolor); line(HLxPos-LFHFmagnify, mappedHFold, (HLxPos+1), mappedHF); // left to right HF line graph } fill(0); stroke(0); if (HLxPos >= (HLWindowWidth+HLWindowY)-1) // reset HL at window end { stroke(0); fill(0); rect(HLWindowY-1, 30, HLWindowWidth+1, HLWindowHeight+1, 5); // HL window clear HLxPos = HLWindowY+1; } ////// draw the Freq plot graph //amp = 1300; // used to test scale accuracy float mappedAmp = map(amp, 0, FreqMaxVal, 200, 0); // float mappedAmp = map(amp, 0, 1000, 200, 0); //freq = 1.50; // used to test positions on graph for accurate scaling if (freq >= && mappedAmp < FreqMaxVal ) { rect(FreqWindowY, 30, FreqWindowWidth, FreqWindowHeight, 5); // draw freq graph window // draw bar freqMappedVal = map(freq, 0, 2, FreqWindowY, FreqWindowWidth+FreqWindowY); freqMappedVal = constrain(freqMappedVal, FreqWindowY, FreqWindowWidth+FreqWindowY); stroke(200, 255, 0); // draw dots for (int i=0; i && powerPointX[i] < FreqWindowWidth+FreqWindowY) // only draw dots in the window ellipse(powerPointX[i], powerPointY[i]+30, 1, 1); // plot a history of data points in red } stroke(250, 5, 180); strokeWeight(3); 90 line(freqMappedVal, FreqWindowHeight+30-1, freqMappedVal, mappedAmp+30 ); fill(255, 0, 0); textSize(12); // draw amps above bar if (mappedAmp > && 1.9 >freq && freq >0) // don't go out of window bounds text(amp, freqMappedVal-10, mappedAmp+25); } // draw PSD graph // reset fill(0); stroke(0); textSize(LabelSize); text("IBI Spectrum (PSD)", PSDWindowY + 10, 0, width, height); rect(PSDWindowY-1, 30, PSDWindowWidth+1, PSDWindowHeight+1, 5); // PSD window if (beatCount > rrData.length/2) // wait before displaying graph in order to gather some valid IBI data { for (int i=0; i < spectrumArr.length/2; i++) { float raw = spectrumArr[i]; // raw = 3500; // sets the value for testing the scale accuracy if (raw>4000) // keep from going into label raw = 4000; float fl = map(raw, 0, 4000, 0, 200); int barSpacing = 26; stroke(0, 255, 255); strokeWeight(7.0); line(PSDxPos+10+ (barSpacing*i), 230, PSDxPos+ 10+(barSpacing*i), 230-fl ); fill(200, 255, 0); textSize(8.5); String rawStr = nf(raw, 1, 1); rawStr = rawStr.substring(0, rawStr.lastIndexOf(".")); if (raw < 3900) { // keep from printing over top label text(rawStr, PSDxPos + + (barSpacing*i), 221-fl); } // print labels if (firstTime) { fill(0); textSize(11); text(PSDlabels[i], PSDxPos + + (barSpacing*i), WaveWindowX15); } } firstTime = false; } else { 91 fill(255, 0, 0); textSize(14); text("Gathering Data", PSDxPos+40, 60); text(10-beatCount, PSDxPos+82, 80); } stroke(0); // at the edge of the screen, go back to the beginning: if (xPos*magnify >= width) { // uses magnify xPos = 1; fill(255, 255, 255); // re-draw main lower waveform window strokeWeight(2.8); rect(1, WaveWindowX, width-3, height-WaveWindowX-2, 5); } } // Serial Event () void serialEvent (Serial myPort) { // get the ASCII string: String inString = myPort.readStringUntil('\n'); if (inString != null) { // trim off any whitespace: inString = trim(inString); if (debug) { println(inString); } if (inString.contains("S") ) { pulseData = false; if (debug) { println("S2: " + inString.replace("S", "")); } inString = inString.replace("S", ""); inByte = float(inString); xPos++; inByte = map(inByte, 300, 600, 100, height-230) - yMod; // } // happens every time there is a beat if (inString.contains("B") ) { // if (playBeep) // Toolkit.getDefaultToolkit().beep(); pulseData = true; if (debug) { 92 println("BPM: " + inString.replace("B", "")); } if (!flatLine) { BPM = int(inString.replace("B", "")); BPMxPos = BPMxPos + 1; } } // happens every time there is a beat if (inString.contains("Q") ) { if (debug) { println("IBI: " + inString.replace("Q", "")); } if (!flatLine) { IBI = int(inString.replace("Q", "")); IBIxPos = IBIxPos+1; // + 1; beatCount++; if (beatCount > 10 && pulseData) { HFold = HF; LFold = LF; HLxPos = HLxPos+LFHFmagnify+1 ; // just to stretch it out a bit } freq = (runningTotal/1000) * 2; seconds account for 1/2 wave data freq = 1/freq; up to Hz runningTotal = 0; amp = P-T; IBI 1/2 wave that just happend mean = P-amp/2; // scale milliseconds to // convert time IBI trending // reset this for next time // measure the size of the freqMappedVal = map(freq, 0, 2, FreqWindowY, FreqWindowWidth+FreqWindowY); freqMappedVal = constrain(freqMappedVal, FreqWindowY, FreqWindowWidth+FreqWindowY); powerPointX[pointCount] = freqMappedVal; // plot the frequency powerPointY[pointCount] = map(amp, 0, FreqMaxVal, 200, 0); // amp determines 'power' of signal pointCount++; // build the powerPoint array if (pointCount == maxDots) { pointCount = 0; 93 } // overflow the powerPoint array ///// if (IBI < lastIBI && goingUp == true) { goingUp = false; T = lastIBI; } if (IBI > lastIBI && goingUp == false) { // check IBI wave trend goingUp = true; P = lastIBI; } if (IBI < T) { T = IBI; point in pulse wave } if (IBI > P) { P = IBI; point in pulse wave } runningTotal += IBI; lastIBI = IBI; // T is the trough // keep track of lowest // P is the trough // keep track of highest int tempIBI = constrain(IBI, 0, 2000); // keeps values from going below zero which will cause and exception in the FFT calcs // IBI = constrain(IBI, 0, 2000); if (beatCount < rrData.length) rrDataStr += tempIBI + ","; else rrDataStr = rrDataStr.substring(rrDataStr.indexOf(",")+1 ) + tempIBI + ","; /// Run data through Fast Fourier Transform (FFT) FFTprocess(); // process PSD Spectrum Data now that the IBI has been updated } } } } //////////////////////////////////// end serial event // PSD Spectrum : Fast Fourier Transform (FFT) calculations void FFTprocess() { String newStr = ""; newStr = rrDataStr.substring(0, rrDataStr.lastIndexOf(",")) ; String[] rrDataArrStr; if (newStr.split(",").length > rrData.length/2) // make sure there are enough data elements to perform FFT calculation { rrDataArrStr = newStr.split(","); 94 for (int i = 0; i< rrDataArrStr.length; i++) { rrData[i] = Float.parseFloat(rrDataArrStr[i]) ; } /// if there are default zero values in the data lets replace them with real values // the number of data elements available is less then the total number we want to evaluate // rrData length is initialzied to the max size of the desired data elements to evaluate // until max size is reached, there will be zeros in the evaluted data (throwing off the PSD calc) // so unti max size is reached will fill remaining rrData with values starting at the beginning of the string // which means the remaining rrData values are duplicates of the first values in the string unitl max size is reached // and then the data starts shifting normally with all real valuess (no dupes) // This at least gives a more accurate graph until all values are filled // if the values are left zeros, the chart will be way off if (rrData.length > rrDataArrStr.length) { for (int i = 0; i< rrData.length - rrDataArrStr.length; i++) { rrData[i+rrDataArrStr.length] = Float.parseFloat(rrDataArrStr[i]) ; } } ///// serial debug printing if (debug) { println ( newStr ); for (int i = 0; i< rrData.length; i++) { print ( rrData[i] + "," ); // rrData[i] = Float.parseFloat(rrDataArrStr[i]) ; } println(" "); } } FloatFFT_1D fftDo = new FloatFFT_1D(rrData.length); float[] fft = new float[rrData.length * 2]; System.arraycopy(rrData, 0, fft, 0, rrData.length); fftDo.realForwardFull(fft); int cnt = 0; for (float d : fft) { cnt++; // print serial if (debug) 95 { print(cnt); print(" fft: "); println(d); } } String ReStr = ""; String ImStr = "0,"; // filler for Im[0] which doesn't exist and shouldn't be used in spectrum calculations // if number of data items is even /* // if n is even a[2*k] = Re[k], 0