8F328P-U 示波器
本帖最后由 eddiewwm 于 2019-1-15 10:23 编辑8F328P-U 示波器
參考:https://create.arduino.cc/projec ... cilloscope&offset=5
更改後的程序:
#define bytesPerPackage 32
#define switch1 4 //sw1 pin
#define switch2 3 //sw2 pin
uint8_t bytesRead;
byte inputBuffer;
byte outputBuffer;
boolean sw1, sw2;
void setup() {
analogReadResolution(8);
pinMode(switch1, INPUT);
digitalWrite(switch1, HIGH);// enable internal pullup
pinMode(switch2, INPUT);
digitalWrite(switch2, HIGH);
ADMUX =B01000000; // select internal reference (Vcc - 5V) and port 5 (A0)
//ADMUX =B00000000; // set external aref and port
ADCSRA = B10101101; // ADC enable, interrupt enable, set default prescaler
ADCSRB = B00000000; // free running mode
sei(); // enable interrupts
ADCSRA |=B01000000; // start first conversion
Serial.begin(115200);
}
void loop() {
sw1 = digitalRead(switch1);
sw2 = digitalRead(switch2);
if (bytesRead >= bytesPerPackage) {// Buffer full. Send the package.
cli();
bytesRead = 0;
// for (uint8_t i = 0; i < bytesPerPackage; i += 2) {
for (uint8_t i = 0; i < bytesPerPackage; i ++) {
byte adch = inputBuffer;
if (!sw1) adch |= B00001000; // switch position in bits 10 & 11 of each byte pair
if (!sw2) adch |= B00000100;
outputBuffer = adch;
}
sei();
Serial.write(outputBuffer, bytesPerPackage);
}
if (Serial.available()) { // incoming byte -> set prescaler
byte inByte = (byte)Serial.read();
cli();
ADCSRA= B10101000|(inByte&B00000111);// last 3 bytes of ADCSRA set the prescaler
sei();
ADCSRA |=B01000000; // start first conversion
}
}
ISR(ADC_vect) {
if (bytesRead < bytesPerPackage) {
inputBuffer = ADCL;
byte temp = ADCH;
bytesRead++;
}
}
配合使用的 Processing程序:
import processing.serial.*;
import java.awt.event.KeyEvent;
// Settings --------------------------------------------------------------------------
int serialBaudRate=115200;
int bufferSize=10000000; // number of samples (memory use: 2 bytes per sample)
float samplesPerLine=1; // increment 1 screen line for each samples
boolean sync=true; // sync to trig
float trigLevelLPF=.0001; // trigLevel lowpass filter (exponential moving average)
boolean hold=false; // pause
int prescaler=5; // ADC prescaler: 3:8 | 4:16 | 5:32 | 6:64 | 7:128
// -----------------------------------------------------------------------------------
Serial serial;
byte[] buffer= new byte;
int writeIndex, prevWriteIndex, readIndex, trigIndex, trigCounter, loopCounter, windowWidth, windowHeight, offset;
float voltageRange, sps, frequency, trigLevel, timer;
int windowX=30;
int windowY=50;
boolean connected=false;
String serialPort;
void settings() {
size(1000, 600);
}
void setup() {
background(0);
surface.setResizable(true);
frameRate(50);
}
void draw() {
windowWidth=width-100;
windowHeight=height-100;
if (!connected) {
background(0, 0, 0);
text("ARDUINO OSCILLOSCOPE\n\nSelect serial port:", 25, 25);
for (int i=0; i<Serial.list().length; i++)
text("F"+(i+1)+" - "+Serial.list(), 25, 80+i*20);
} else {
background(0, 0, 0);
// update frequency counters every second
loopCounter++;
if (loopCounter>frameRate) {
loopCounter=0;
float elapsedSeconds=(millis()-timer)/1000;
timer=millis();
sps=(writeIndex-prevWriteIndex)/elapsedSeconds;// sample rate
if (sps<0)sps+=bufferSize;
prevWriteIndex=writeIndex;
frequency=trigCounter/elapsedSeconds; // signal frequency
trigCounter=0;
}
/*
// read switch position & set voltage range
boolean switch1=((buffer&(byte)8)==8);
boolean switch2=((buffer&(byte)4)==4);
if (!switch1&&!switch2) voltageRange=20;
if (!switch1&&switch2) voltageRange=10;
if (switch1&&!switch2) voltageRange=6.64;
if (switch1&&switch2) voltageRange=5;
*/
voltageRange=5;
// print voltage scale
for (int n=0; n<=10; n++)
text(nf(voltageRange/10*n, 2, 2)+"V", windowX+windowWidth+5, windowY+windowHeight-(n*windowHeight/10));
// print interface and statistics
text(" ZOOM | SYNC: "+sync+" | HOLD: "+hold+" | TRIG LPF | PRESCALER: "+nf((pow(2, prescaler)), 1, 0)+" | [<--->] OFFSET", 25, 25);
text("frequency: "+nf(frequency, 5, 2)+"Hz"
+" | average DCV: "+nf(trigLevel/256*voltageRange, 2, 2)+"V"
+" | samplerate: "+nf(sps, 5, 2)+"Hz"
+" | samples per line: "+samplesPerLine
+" | division: "+samplesPerLine/sps*(float)width*100+"ms", 25, height-20);
// draw trigLevel (= average voltage) line
stroke(0, 0, 100);
int trigLevelHeight=(int)(trigLevel*(float)windowHeight/256);
line(windowX, windowY+windowHeight-trigLevelHeight, windowX+windowWidth, windowY+windowHeight-trigLevelHeight);
// draw grid
stroke(50);
for (float n=0; n<=windowWidth; n+=(float)windowWidth/10)
line(n+windowX, windowY, n+windowX, windowHeight+windowY);
for (float n=0; n<=windowHeight; n+=(float)windowHeight/10)
line(windowX, n+windowY, windowX+windowWidth, n+windowY);
// ------------------------------
// DRAW WAVEFORM
// ------------------------------
stroke(255);
float prevSampleValue=0;
if (sync) readIndex=trigIndex; // sync: start reading from last trig position
if (!sync) readIndex=writeIndex; // no sync: start reading from last sample we received
readIndex+=offset;
float lineIncr=(float)1/samplesPerLine;
if (lineIncr<1) lineIncr=1;
for (float line=0; line<windowWidth; line+=lineIncr) { // cycle screen lines (from right to left)
float sampleValue=(float)getValueFromBuffer((int)((float)readIndex-line*samplesPerLine)); // get the value for the screen line
sampleValue*=(float)windowHeight/256; // scale to windowHeight
if (line>0)
line(windowX+windowWidth-line,
windowY+windowHeight-prevSampleValue,
windowX+windowWidth-line-lineIncr,
windowY+windowHeight-sampleValue);
prevSampleValue=sampleValue;
}
// ------------------------------
// BUFFER INCOMING BYTES & TRIG
// ------------------------------
if (hold) {
serial.clear(); // HOLD: don't receive samples; clear serial buffer
} else {
while (serial.available ()>0) { // RUN: receive samples
writeIndex++;
if (writeIndex>=bufferSize) writeIndex=0; // handle overflow
//buffer=(byte)serial.read(); // add 1 sample (2 bytes) to buffer
buffer=(byte)serial.read(); // add 1 sample (2 bytes) to buffer
// buffer=(byte)serial.read();
trigLevel=trigLevel*(1-trigLevelLPF)+(float)getValueFromBuffer(writeIndex)*trigLevelLPF; // level for trigger intersection = exponential moving average of voltage
if (getValueFromBuffer(writeIndex)>=trigLevel&& getValueFromBuffer(writeIndex-1)<trigLevel) { // rising intersect detected
trigIndex=writeIndex; // set trigIndex (index of buffer that corresponds to last trig)
trigCounter++; // count trigs (to calculate the frequency)
}
}
}
}
}
// Read value from buffer
int getValueFromBuffer(int index) {
while (index<0) index+=bufferSize; // handle overflow of circular buffer
//return((buffer&3)<<8 | buffer&0xff); // convert bytes to int
return(buffer&0xff); // convert bytes to int
}
// Handle keys
void keyPressed() {
if (key == CODED) {
if (connected) {
if (keyCode == KeyEvent.VK_F1) {
samplesPerLine*=1.1;
if (samplesPerLine*windowWidth>bufferSize) samplesPerLine=bufferSize/windowWidth;
}
if (keyCode == KeyEvent.VK_F2) {
samplesPerLine/=1.1;
if (samplesPerLine<1/(float)windowWidth) samplesPerLine=1/(float)windowWidth;
}
if (keyCode == KeyEvent.VK_F3) {
sync=!sync;
}
if (keyCode == KeyEvent.VK_F4) {
hold=!hold;
}
if (keyCode == KeyEvent.VK_F5) {
if (trigLevelLPF<.01) trigLevelLPF*=10;
}
if (keyCode == KeyEvent.VK_F6) {
if (trigLevelLPF>.000001) trigLevelLPF/=10;
}
if (keyCode == KeyEvent.VK_F7) {
if (prescaler>3) prescaler--;
serial.write((byte)prescaler);
}
if (keyCode == KeyEvent.VK_F8) {
if (prescaler<7) prescaler++;
serial.write((byte)prescaler);
}
if (keyCode == LEFT) {
offset-=samplesPerLine*20;
if (offset<-bufferSize) offset=-bufferSize;
}
if (keyCode == RIGHT) {
offset+=samplesPerLine*20;
if (offset>0) offset=0;
}
} else {
serial = new Serial(this, Serial.list(), serialBaudRate);
serial.write((byte)prescaler);
connected=true;
}
}
}
另一個初學型示波器範例:
Arduino - Oscilloscope (poor Man's Oscilloscope)
https://www.instructables.com/id/Arduino-Oscilloscope-poor-mans-Oscilloscope/
// Oscilloscope
// Input defined by ANALOG_IN
// SIG_OUT true puts a 2kHz wave on DIGITAL_OUT for testing.
#define ANALOG_IN 0
#define DIGITAL_OUT 13
bool SIG_OUT = true;
void setup() {
analogReadResolution(10);
Serial.begin(9600);
//Serial.begin(115200);
// Generate a signal to examine (testing)
if (SIG_OUT) {
pinMode(DIGITAL_OUT, OUTPUT);
// initialize timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1= 0;
OCR1A = 31250; // compare match register 16MHz/256/2Hz
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << OCIE1A);// enable timer compare interrupt
interrupts(); // enable all interrupts
}
}
// Interrupt based
ISR(TIMER1_COMPA_vect) {
digitalWrite(DIGITAL_OUT, digitalRead(DIGITAL_OUT) ^ 1); // Toggle
}
void loop() {
int val = analogRead(ANALOG_IN);
Serial.write( 0xff );
Serial.write( (val >> 8) & 0xff );
Serial.write( val & 0xff );
}
配合使用的Processing程序:
/*
* Oscilloscope
* Gives a visual rendering of analog pin in realtime.
*
* ---------------- IMPROVEMENTS ------------------
* Updates by John Porter, 2/7/2014
* Added ability to move waveform left or right.
* Added gridlines (bounds and minor).
* Added ability to pause/resume.
* Added ability to measure time.
* General usability improvements.
*
* --------------- ORIGINAL PROJECT ---------------
* This project is part of Accrochages
* See http://accrochages.drone.ws
* (c) 2008 Sofian Audry ([email protected])
* ------------------------------------------------
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// * ------------------ HOT KEYS ------------------
final char T_UP = 'w'; // Translate waveform up
final char T_DOWN = 's'; // down
final char T_LEFT = 'a'; // left
final char T_RIGHT = 'd'; // right
final char Z_IN = 'c'; // Horizontal zoom in
final char Z_OUT = 'z'; // out
final char S_IN = 'e'; // Vertical scale in
final char S_OUT = 'q'; // out
final char MGL_UP = 'r'; // Minor grid lines increase
final char MGL_DOWN = 'f'; // decrease
final char TOG_PAUSE= 'p'; // Toggle pause (unpause resets waveform)
final char RESET_AXIS = ' '; // Reset axis settings
final char MEAS_TIME= 'x'; // Adds and/or highlights vertical bars (time measurement)
final char BAR_LEFT = ','; // Move highlighted vertical bar left (can also mouse click)
final char BAR_RIGHT= '.'; // right
// * ----------------------------------------------
// * --------------- STARTING STATE ---------------
float zoom = 1.0;
float scale = 0.5;
int centerV = 0;
int centerH = 0;
int gridLines = 0;
int com_port= 0; // Index number in Serial.list
// * ----------------------------------------------
// Global vars
import processing.serial.*;
Serial port; // Create object from Serial class
int val; // Data received from the serial port
long valTime; // Time data was received
int[] values;
long[] times;
float voltage;
float measTime = 0;
int timeMode = 0;
int[] timeBars = {0, 0};
PFont f;
boolean pause;
// Setup
void setup() {
size(1280, 480);
port = new Serial(this, Serial.list(), 9600); // Com port specified here
values = new int;
times = new long;
timeBars = width/3;
timeBars = 2*width/3;
pause = false;
smooth();
f = createFont("Arial", 16, true);
}
// Read value from serial stream
int getValue() {
int value = -1;
while (port.available () >= 3) {
if (port.read() == 0xff) {
value = (port.read() << 8) | (port.read());
}
}
return value;
}
// Get a y-value for the datapoint, varies based on axis settings
int getY(int val) {
return (int)(height/2 -(val-512+centerV)*scale / 1023.0f * (height - 1));
}
// Push the values in the data array
void pushValue(int value) {
for (int i=0; i<width-1; i++)
values = values;
values = value;
}
// Push the timestamps in the time array
void pushTime(long time) {
for (int i=0; i<width-1; i++)
times = times;
times = time;
}
// Draw waveform
void drawLines() {
int x0 = 0, x1 = 0, y0 = 0, y1 = 0;
stroke(255,255,0);
for (int i=0; i<width; i++) {
x1 = round(width - ((width-i) * zoom) + centerH);
y1 = getY(values);
if(i > 1)
line(x0, y0, x1, y1);
x0 = x1;
y0 = y1;
}
}
// Draw gridlines (bounds, minor)
void drawGrid() {
// Get scaled values for bounds
int pFive = getY(1023);
int zero= getY(0);
// Draw voltage bounds
stroke(255, 0, 0);
line(0, pFive-1, width, pFive-1);
line(0, zero+1, width, zero+1);
// Add voltage bound text
textFont(f, 10);
fill(255, 0, 0);
text("+5V", 5, pFive+12);
text(" 0V", 5, zero-4);
// Draw minor grid lines
int gridVal = 0;
stroke(75, 75, 75);
for (int i = 0; i < gridLines; i++) {
gridVal = getY(round((i+1.0)*(1023.0 / (gridLines+1.0))));
line(0, gridVal, width, gridVal);
}
// Add minor grid line text
if (gridLines > 0) {
textFont(f, 16);
fill(204, 102, 0);
float scaleVal = truncate(5.0f / (gridLines+1), 3);
text("Grid: " + scaleVal + "V", 1170, height-12);
}
// Print difference between vertical 'time' bars
if (timeMode > 0) {
textFont(f, 16);
fill(204, 102, 0);
int idx0 = round(width + (timeBars - width - centerH)/zoom);
int idx1 = round(width + (timeBars - width - centerH)/zoom);
// Ensure time bars are over a recorded portion of the waveform
if(idx1 < 0 || idx0 < 0 || idx1 > (width-1) || idx0 > (width-1) || times == 0 || times == 0)
text("Time: N/A", 30, height-12);
else{
float timeDiff = truncate((times - times)/2000000.0,2);
text("Time: " + timeDiff + "ms", 30, height-12);
}
}
}
// Draw vertical 'time bars' (seperate from above for better layering)
void drawVertLines(){
stroke(75, 75, 75);
if (timeMode == 1) {
line(timeBars, 0, timeBars, height);
stroke(100, 100, 255);
line(timeBars, 0, timeBars, height);
}
else if (timeMode == 2) {
line(timeBars, 0, timeBars, height);
stroke(100, 255, 100);
line(timeBars, 0, timeBars, height);
}
}
// Truncate a floating point number
float truncate(float x, int digits) {
float temp = pow(10.0, digits);
return round( x * temp ) / temp;
}
// When a key is pressed down or held...
void keyPressed() {
switch (key) {
case T_UP: centerV += 10/scale; break; // Move waveform up
case T_DOWN: centerV -= 10/scale; break; // Move waveform down
case T_RIGHT: centerH += 10/scale; break; // Move waveform right
case T_LEFT: centerH -= 10/scale; break; // Move waveform left
case MGL_UP: // Increase minor grid lines
if (gridLines < 49)
gridLines += 1;
break;
case MGL_DOWN: // Decrease minor grid lines
if (gridLines > 0)
gridLines -= 1;
break;
case BAR_LEFT: // Move the time bar left (also mouse click)
if (timeMode == 1 && timeBars > 0)
timeBars -= 1;
else if (timeMode == 2 && timeBars > 0)
timeBars -= 1;
break;
case BAR_RIGHT: // Move the time bar right (also mouse click)
if (timeMode == 1 && timeBars < width-1)
timeBars += 1;
else if (timeMode == 2 && timeBars < width-1)
timeBars += 1;
break;
}
}
// When a key is released...
void keyReleased() {
println(key+": "+(int)key);
switch (key) {
case Z_IN: // Zoom horizontal
zoom *= 2.0f;
if ( (int) (width / zoom) <= 1 )
zoom /= 2.0f;
break;
case Z_OUT: // Zoom horizontal
zoom /= 2.0f;
if (zoom < 1.0f)
zoom *= 2.0f;
break;
case S_IN: scale*=2; break; // Scale vertical
case S_OUT: scale /= 2; break; // Scale vertical
case RESET_AXIS: // Reset all scaling
centerV = 0; centerH = 0;
scale = 0.5; zoom= 1; gridLines = 0;
break;
case MEAS_TIME: timeMode = (timeMode + 1) % 3; break; // Change the vertical bars (off, left bar, right bar)
case TOG_PAUSE: // Toggle waveform pausing
if (pause) {
centerH = 0;
for (int i=0; i<width; i++){
values = 0; // Clear data on resume
times = 0;
}
}
pause = !pause;
}
}
// Use mouse clicks to quickly move vertical bars (if highlighted)
void mousePressed() {
if(timeMode == 1)
timeBars = mouseX;
else if(timeMode == 2)
timeBars = mouseX;
}
// Primary drawing function
void draw()
{
background(0);
drawGrid();
// Get current voltage, time of reading
val = getValue();
valTime = System.nanoTime();
// If not paused
if (!pause && val != -1) {
// Push value/time onto array
pushValue(val);
pushTime(valTime);
// Print current voltage reading
textFont(f, 16);
fill(204, 102, 0);
voltage = truncate(5.0*val / 1023, 1);
text("Voltage: " + voltage + "V", 1170, 30);
}
drawLines();
drawVertLines();
} 把以上範例改以VUSB代替串口:
Arduino程序:
// Oscilloscope
// Input defined by ANALOG_IN
// SIG_OUT true puts a 2kHz wave on DIGITAL_OUT for testing.
#include <HIDSerial.h>
HIDSerial serial;
#define ANALOG_IN 0
#define DIGITAL_OUT 13
bool SIG_OUT = true;
void setup() {
analogReadResolution(8); //use 1-byte A/D
serial.begin(); //HID
//Serial.begin(9600);
//Serial.begin(115200);
// Generate a signal to examine (testing)
if (SIG_OUT) {
pinMode(DIGITAL_OUT, OUTPUT);
// initialize timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1= 0;
OCR1A = 31250; // compare match register 16MHz/256/2Hz
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << OCIE1A);// enable timer compare interrupt
interrupts(); // enable all interrupts
}
}
// Interrupt based
ISR(TIMER1_COMPA_vect) {
digitalWrite(DIGITAL_OUT, digitalRead(DIGITAL_OUT) ^ 1); // Toggle
}
//byte val = 0;
void loop() {
byte val = analogRead(ANALOG_IN);
/*
Serial.write( 0xff );
Serial.write( (val >> 8) & 0xff );
Serial.write( val & 0xff );
*/
if (val==0) val=1; //use 1-byte only and reserve 0 for special use
serial.write( val );
serial.poll();
}
配合使用的Processing程序:
/*
* Oscilloscope
* Gives a visual rendering of analog pin in realtime.
*
* ---------------- IMPROVEMENTS ------------------
* Updates by John Porter, 2/7/2014
* Added ability to move waveform left or right.
* Added gridlines (bounds and minor).
* Added ability to pause/resume.
* Added ability to measure time.
* General usability improvements.
*
* --------------- ORIGINAL PROJECT ---------------
* This project is part of Accrochages
* See http://accrochages.drone.ws
* (c) 2008 Sofian Audry ([email protected])
* ------------------------------------------------
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// * ------------------ HOT KEYS ------------------
final char T_UP = 'w'; // Translate waveform up
final char T_DOWN = 's'; // down
final char T_LEFT = 'a'; // left
final char T_RIGHT = 'd'; // right
final char Z_IN = 'c'; // Horizontal zoom in
final char Z_OUT = 'z'; // out
final char S_IN = 'e'; // Vertical scale in
final char S_OUT = 'q'; // out
final char MGL_UP = 'r'; // Minor grid lines increase
final char MGL_DOWN = 'f'; // decrease
final char TOG_PAUSE= 'p'; // Toggle pause (unpause resets waveform)
final char RESET_AXIS = ' '; // Reset axis settings
final char MEAS_TIME= 'x'; // Adds and/or highlights vertical bars (time measurement)
final char BAR_LEFT = ','; // Move highlighted vertical bar left (can also mouse click)
final char BAR_RIGHT= '.'; // right
// * ----------------------------------------------
// * --------------- STARTING STATE ---------------
float zoom = 1.0;
float scale = 0.5;
int centerV = 0;
int centerH = 0;
int gridLines = 0;
int com_port= 1; // Index number in Serial.list
// * ----------------------------------------------
int val; // Data received from the serial port
long valTime; // Time data was received
int[] values;
long[] times;
float voltage;
float measTime = 0;
int timeMode = 0;
int[] timeBars = {0, 0};
PFont f;
boolean pause;
/*****************************************************
Host software for HID-class USB serial communication.
It allows connecting to a HID serial device (16c0:05df),
sending (up to 32 bytes per packet) and receiving
strings from the device. The code uses a slightly modified
version of the g4p library for user interface, and the
HIDAPI library for handling HID requests.
The code was initially written by Chaniel Chadowitz
and modified by Ray Wang (Rayshobby LLC). The code is published
under Creative Commons Attribution-ShareAlike 3.0 license.
*************************************************************/
import g4p_controls.*;
import com.codeminders.hidapi.HIDDeviceInfo;
import com.codeminders.hidapi.HIDManager;
import com.codeminders.hidapi.HIDDevice;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.awt.Font;
GButton connectButton;
boolean paused;
String serialText = new String();
int VENDOR_ID = 0x16c0;
int PRODUCT_ID = 0x05df;
HIDDevice device = null;
Boolean device_initialized = false;
byte value1 = 0;
int value = 0;
// Setup
void setup() {
size(1280, 480);
G4P.setGlobalColorScheme(5);
connectButton = new GButton(this, 10, 15, 100, 20, "Connect");
connectButton.setTextBold();
device_initialized = false;
values = new int;
times = new long;
timeBars = width/3;
timeBars = 2*width/3;
pause = false;
smooth();
f = createFont("Arial", 16, true);
}
// Get a y-value for the datapoint, varies based on axis settings
int getY(int val) {
return (int)(height/2 -(val-512+centerV)*scale / 1023.0f * (height - 1));
}
// Push the values in the data array
void pushValue(int value) {
for (int i=0; i<width-1; i++)
values = values;
values = value;
}
// Push the timestamps in the time array
void pushTime(long time) {
for (int i=0; i<width-1; i++)
times = times;
times = time;
}
// Draw waveform
void drawLines() {
int x0 = 0, x1 = 0, y0 = 0, y1 = 0;
stroke(255, 255, 0);
for (int i=0; i<width; i++) {
x1 = round(width - ((width-i) * zoom) + centerH);
y1 = getY(values*4);
if (i > 1)
line(x0, y0, x1, y1);
x0 = x1;
y0 = y1;
}
}
// Draw gridlines (bounds, minor)
void drawGrid() {
// Get scaled values for bounds
int pFive = getY(1023);
int zero= getY(0);
// Draw voltage bounds
stroke(255, 0, 0);
line(0, pFive-1, width, pFive-1);
line(0, zero+1, width, zero+1);
// Add voltage bound text
textFont(f, 10);
fill(255, 0, 0);
text("+5V", 5, pFive+12);
text(" 0V", 5, zero-4);
// Draw minor grid lines
int gridVal = 0;
stroke(75, 75, 75);
for (int i = 0; i < gridLines; i++) {
gridVal = getY(round((i+1.0)*(1023.0 / (gridLines+1.0))));
line(0, gridVal, width, gridVal);
}
// Add minor grid line text
if (gridLines > 0) {
textFont(f, 16);
fill(204, 102, 0);
float scaleVal = truncate(5.0f / (gridLines+1), 3);
text("Grid: " + scaleVal + "V", 1170, height-12);
}
// Print difference between vertical 'time' bars
if (timeMode > 0) {
textFont(f, 16);
fill(204, 102, 0);
int idx0 = round(width + (timeBars - width - centerH)/zoom);
int idx1 = round(width + (timeBars - width - centerH)/zoom);
// Ensure time bars are over a recorded portion of the waveform
if (idx1 < 0 || idx0 < 0 || idx1 > (width-1) || idx0 > (width-1) || times == 0 || times == 0)
text("Time: N/A", 30, height-12);
else {
float timeDiff = truncate((times - times)/2000000.0, 2);
text("Time: " + timeDiff + "ms", 30, height-12);
}
}
}
// Draw vertical 'time bars' (seperate from above for better layering)
void drawVertLines() {
stroke(75, 75, 75);
if (timeMode == 1) {
line(timeBars, 0, timeBars, height);
stroke(100, 100, 255);
line(timeBars, 0, timeBars, height);
} else if (timeMode == 2) {
line(timeBars, 0, timeBars, height);
stroke(100, 255, 100);
line(timeBars, 0, timeBars, height);
}
}
// Truncate a floating point number
float truncate(float x, int digits) {
float temp = pow(10.0, digits);
return round( x * temp ) / temp;
}
// When a key is pressed down or held...
void keyPressed() {
switch (key) {
case T_UP:
centerV += 10/scale;
break; // Move waveform up
case T_DOWN:
centerV -= 10/scale;
break; // Move waveform down
case T_RIGHT:
centerH += 10/scale;
break; // Move waveform right
case T_LEFT:
centerH -= 10/scale;
break; // Move waveform left
case MGL_UP: // Increase minor grid lines
if (gridLines < 49)
gridLines += 1;
break;
case MGL_DOWN: // Decrease minor grid lines
if (gridLines > 0)
gridLines -= 1;
break;
case BAR_LEFT: // Move the time bar left (also mouse click)
if (timeMode == 1 && timeBars > 0)
timeBars -= 1;
else if (timeMode == 2 && timeBars > 0)
timeBars -= 1;
break;
case BAR_RIGHT: // Move the time bar right (also mouse click)
if (timeMode == 1 && timeBars < width-1)
timeBars += 1;
else if (timeMode == 2 && timeBars < width-1)
timeBars += 1;
break;
}
}
// When a key is released...
void keyReleased() {
println(key+": "+(int)key);
switch (key) {
case Z_IN: // Zoom horizontal
zoom *= 2.0f;
if ( (int) (width / zoom) <= 1 )
zoom /= 2.0f;
break;
case Z_OUT: // Zoom horizontal
zoom /= 2.0f;
if (zoom < 1.0f)
zoom *= 2.0f;
break;
case S_IN:
scale*=2;
break; // Scale vertical
case S_OUT:
scale /= 2;
break; // Scale vertical
case RESET_AXIS: // Reset all scaling
centerV = 0;
centerH = 0;
scale = 0.5;
zoom= 1;
gridLines = 0;
break;
case MEAS_TIME:
timeMode = (timeMode + 1) % 3;
break; // Change the vertical bars (off, left bar, right bar)
case TOG_PAUSE: // Toggle waveform pausing
if (pause) {
centerH = 0;
for (int i=0; i<width; i++) {
values = 0; // Clear data on resume
times = 0;
}
}
pause = !pause;
}
}
// Use mouse clicks to quickly move vertical bars (if highlighted)
void mousePressed() {
if (timeMode == 1)
timeBars = mouseX;
else if (timeMode == 2)
timeBars = mouseX;
}
// Primary drawing function
void draw() {
background(0);
if ( device != null && !paused ) {
deviceRead();
}
drawGrid();
// Get current voltage, time of reading
val = value;
//valTime = System.nanoTime();
// If not paused
if (!pause && val != -1) {
// Push value/time onto array
pushValue(val);
pushTime(valTime);
// Print current voltage reading
textFont(f, 16);
fill(204, 102, 0);
voltage = truncate(3.3*val / 256, 2);
text("Voltage: " + voltage + "V", 1170, 30);
}
drawLines();
drawVertLines();
}
public void deviceInitialize() {
if (!device_initialized) {
device_initialized = true;
com.codeminders.hidapi.ClassPathLibraryLoader
.loadNativeHIDLibrary();
}
}
public void deviceFindFirst() {
deviceInitialize();
HIDDeviceInfo[] infos = deviceFindAllDescriptors();
if (infos.length > 0) {
try {
device = infos.open();
}
catch (Exception e) {
device = null;
}
}
}
public HIDDeviceInfo[] deviceFindAllDescriptors() {
deviceInitialize();
List<HIDDeviceInfo> devlist = new ArrayList<HIDDeviceInfo>();
try {
HIDManager hidManager = HIDManager.getInstance();
HIDDeviceInfo[] infos = hidManager.listDevices();
for (HIDDeviceInfo info : infos) {
if (info.getVendor_id() == VENDOR_ID
&& info.getProduct_id() == PRODUCT_ID) {
devlist.add(info);
}
}
}
catch (Exception e) {
}
return devlist.toArray(new HIDDeviceInfo);
}
public void deviceRead() {
try {
device.disableBlocking();
byte[] data = new byte;
int read = device.read(data);
if (read > 0) {
for (int i=0; i<read; i++) {
if (data!=0) {
value1 = data;
//convert signed byte to unsigned byte
if (value1 >=0)
{
value = value1;
} else {
value = int (value1 + 255);
}
}
}
}
}
catch(IOException ioe) {
//ioe.printStackTrace();
System.out.println("deviceRead error");
}
}
public void handleButtonEvents(GButton button, GEvent event) {
if ( event == GEvent.CLICKED ) {
if ( button.equals(connectButton) ) {
if (device!=null) {
try {
device.close();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
device = null;
connectButton.setText("Connect");
connectButton.setTextBold();
value = 0;
} else {
deviceFindFirst();
connectButton.setText("Disconnect");
connectButton.setTextBold();
}
}
}
}
以上的範例的實用性不大,但可作程序操練之用!:);P :lol有高清无码大图嘛 效果確實差得不能見人!:lol
在網上看同一些用聲卡的示波器程序,這兩款看來很好:
虚拟示波器 0.94(利用声卡虚拟示波器)绿色版
http://www.7edown.com/xiazai/1562.html
Soundcard Oscilloscope
https://www.zeitnitz.eu/scope_en
按書本《玩轉Arduino電子制作 - 吳漢清 編著》P.227範例更改後的程序:
#include "U8glib.h"
// setup u8g object, please remove comment from one of the following constructor calls
// IMPORTANT NOTE: The following list is incomplete. The complete list of supported
// devices with all constructor calls is here: https://github.com/olikraus/u8glib/wiki/device
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0); // I2C / TWI
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST); // Fast I2C / TWI
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK);// Display which does not send AC
int Input = A0;
int Key_add = 8;
int Key_sub = 9;
int Key_hold = 10;
int x, y;
int i, i1, i2, V_min, V_max, V_mid, t, t0, t1, sta, Key = 1, hold = 0;
long Freq;
float Vpp;
int Y;
int Buffer;
void sample() {
for (i = 0; i < 192; i++) {
Buffer = ADCH;
switch (Key) {
case 1: delayMicroseconds(3); //__asm__("nop\n\t");//0.02 ms/div
break;
case 2: delayMicroseconds(10);//0.05 ms/div
break;
case 3: delayMicroseconds(21);//0.1 ms/div
//__asm__("nop\n\t");
break;
case 4: delayMicroseconds(43);//0.2 ms/div
break;
case 5: delayMicroseconds(110);//0.5 ms/div
break;
case 6: delayMicroseconds(222);//1 ms/div
break;
case 7: delayMicroseconds(444);//2 ms/div
break;
case 8: delayMicroseconds(1130);//5 ms/div
break;
case 9: delayMicroseconds(2220);//10 ms/div
break;
default: break;
}
}
for (i = 0; i < 192; i++) {
Serial.write(Buffer);
}
}
void Measure() {
V_max = Buffer;
V_min = Buffer;
for (i = 0; i < 192; i++) {
if (Buffer > V_max) V_max = Buffer;
if (Buffer < V_min) V_min = Buffer;
}
V_mid = (V_max + V_min) / 2;
Vpp = (V_max - V_min) * 5.0 / 255;
for (i = 0; i < 197; i++) {
if (Buffer < V_mid && Buffer >= V_mid) {
i1 = i;
break;
}
}
for (i = i1 + 1; i < 98 + i1; i++) {
if (Buffer < V_mid && Buffer >= V_mid) {
i2 = i;
break;
}
}
t = i2 - i1;
if (t > 0) Freq = 8000 / t;
elseFreq = 0;
}
void Transform() {
for (sta = 0; sta < 96; sta++) {
if (Buffer < 128 && Buffer > 128) break;
}
for (i = 0; i < 96; i++) {
Y = 63 - (Buffer >> 2);
}
}
void draw() {
for (x = 0; x < 95; x++) u8g.drawLine(x, Y, x, Y);
u8g.drawFrame(0, 0, 97, 64);
u8g.drawLine(48, 0, 48, 63);
u8g.drawLine(0, 32, 96, 32);
for (x = 0; x < 96; x += 8) u8g.drawLine(x, 31, x, 33);
for (y = 0; y < 64; y += 8) u8g.drawLine(47, y, 49, y);
for (x = 8; x < 96; x += 8) {
for (y = 8; y < 64; y += 8) u8g.drawPixel(x, y);
}
u8g.drawStr(98, 7, "MS/div");
u8g.drawStr(98, 23, "V/div");
u8g.drawStr(98, 30, "0.625");
u8g.drawStr(98, 40, "Vpp");
u8g.setPrintPos(98, 47);
u8g.print(Vpp);
u8g.drawStr(118, 47, "V");
u8g.drawStr(98, 55, "F(Hz)");
switch (Key) {
case 1:
u8g.drawStr(98, 14, "0.02");
u8g.setPrintPos(98, 62);
u8g.print(Freq * 50);
break;
case 2:
u8g.drawStr(98, 14, "0.05");
u8g.setPrintPos(98, 62);
u8g.print(Freq * 20);
break;
case 3:
u8g.drawStr(98, 14, "0.1");
u8g.setPrintPos(98, 62);
u8g.print(Freq * 10);
break;
case 4:
u8g.drawStr(98, 14, "0.2");
u8g.setPrintPos(98, 62);
u8g.print(Freq * 5);
break;
case 5:
u8g.drawStr(98, 14, "0.5");
u8g.setPrintPos(98, 62);
u8g.print(Freq * 2);
break;
case 6:
u8g.drawStr(98, 14, "1");
u8g.setPrintPos(98, 62);
u8g.print(Freq);
break;
case 7:
u8g.drawStr(98, 14, "2");
u8g.setPrintPos(98, 62);
u8g.print(Freq / 2);
break;
case 8:
u8g.drawStr(98, 14, "5");
u8g.setPrintPos(98, 62);
u8g.print(Freq / 5);
break;
case 9:
u8g.drawStr(98, 14, "10");
u8g.setPrintPos(98, 62);
u8g.print(Freq / 10);
break;
default: break;
}
}
void Key_scan() {
if (digitalRead(Key_add) == LOW) {
while (digitalRead(Key_add) == LOW);
Key ++;
if (Key == 10)Key = 9;
delay(10);
}
if (digitalRead(Key_sub) == LOW) {
while (digitalRead(Key_sub) == LOW);
Key --;
if (Key == 0)Key = 1;
delay(10);
}
if (digitalRead(Key_hold) == LOW) {
while (digitalRead(Key_hold) == LOW);
hold == ~ hold;
delay(10);
}
}
void setup() {
//for 32MHz clock only
sysClock(INT_OSC); //use internal 32MHz RC clock
CLKPR = 0x80;
CLKPR = 0x00; //Divider=1, =>32MHz/1 = 32MHz
//
pinMode(Key_add, INPUT_PULLUP);
pinMode(Key_sub, INPUT_PULLUP);
pinMode(Key_hold, INPUT_PULLUP);
ADMUX = 0x60; // use Vcc reference, 8-bit left align
//ADMUX = 0xa0; // use 2.048V reference, 8-bit left align
//ADMUX = 0xe0; // use 1.024V reference, 8-bit left align
Serial.begin(115200);
ADCSRA = 0xe2;
u8g.setFont(u8g_font_5x7);
}
void loop() {
sample();
Measure();
Transform();
Key_scan();
if (hold == 0) {
u8g.firstPage();
do {
draw();
}
while ( u8g.nextPage());
}
}
页:
[1]