极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 113|回复: 4

8F328P-U 示波器

[复制链接]
发表于 6 天前 | 显示全部楼层 |阅读模式
本帖最后由 eddiewwm 于 2019-1-15 10:23 编辑

8F328P-U 示波器
參考:https://create.arduino.cc/projec ... cilloscope&offset=5

更改後的程序:
  1. #define bytesPerPackage 32
  2. #define switch1 4               //sw1 pin
  3. #define switch2 3               //sw2 pin

  4. uint8_t bytesRead;
  5. byte inputBuffer[bytesPerPackage];
  6. byte outputBuffer[bytesPerPackage];
  7. boolean sw1, sw2;

  8. void setup() {
  9.   analogReadResolution(8);
  10.   pinMode(switch1, INPUT);
  11.   digitalWrite(switch1, HIGH);  // enable internal pullup
  12.   pinMode(switch2, INPUT);
  13.   digitalWrite(switch2, HIGH);
  14. ADMUX =  B01000000;         // select internal reference (Vcc - 5V) and port 5 (A0)
  15. //  ADMUX =  B00000000;           // set external aref and port
  16.   ADCSRA = B10101101;           // ADC enable, interrupt enable, set default prescaler
  17.   ADCSRB = B00000000;           // free running mode
  18.   sei();            // enable interrupts
  19.   ADCSRA |=B01000000;           // start first conversion
  20.   Serial.begin(115200);
  21. }

  22. void loop() {
  23.   sw1 = digitalRead(switch1);
  24.   sw2 = digitalRead(switch2);
  25.   if (bytesRead >= bytesPerPackage) {  // Buffer full. Send the package.
  26.     cli();
  27.     bytesRead = 0;
  28.    // for (uint8_t i = 0; i < bytesPerPackage; i += 2) {
  29.    for (uint8_t i = 0; i < bytesPerPackage; i ++) {
  30.       byte adch = inputBuffer[i];
  31.       if (!sw1) adch |= B00001000;      // switch position in bits 10 & 11 of each byte pair
  32.       if (!sw2) adch |= B00000100;
  33.       outputBuffer[i] = adch;
  34.     }
  35.     sei();
  36.     Serial.write(outputBuffer, bytesPerPackage);
  37.   }
  38.   
  39.   if (Serial.available()) {                // incoming byte -> set prescaler
  40.     byte inByte = (byte)Serial.read();
  41.     cli();
  42.     ADCSRA= B10101000|(inByte&B00000111);  // last 3 bytes of ADCSRA set the prescaler
  43.     sei();
  44.     ADCSRA |=B01000000;                    // start first conversion
  45.   }
  46. }

  47. ISR(ADC_vect) {
  48.   if (bytesRead < bytesPerPackage) {
  49.     inputBuffer[bytesRead] = ADCL;
  50.     byte temp = ADCH;
  51.     bytesRead++;
  52.   }
  53. }
复制代码

配合使用的 Processing程序
  1. import processing.serial.*;
  2. import java.awt.event.KeyEvent;

  3. // Settings --------------------------------------------------------------------------
  4. int serialBaudRate=115200;
  5. int bufferSize=10000000;      // number of samples (memory use: 2 bytes per sample)
  6. float samplesPerLine=1;       // increment 1 screen line for each [n] samples
  7. boolean sync=true;            // sync to trig
  8. float trigLevelLPF=.0001;     // trigLevel lowpass filter (exponential moving average)
  9. boolean hold=false;           // pause
  10. int prescaler=5;              // ADC prescaler: 3:8 | 4:16 | 5:32 | 6:64 | 7:128
  11. // -----------------------------------------------------------------------------------

  12. Serial serial;
  13. byte[] buffer= new byte[bufferSize*2];
  14. int writeIndex, prevWriteIndex, readIndex, trigIndex, trigCounter, loopCounter, windowWidth, windowHeight, offset;
  15. float voltageRange, sps, frequency, trigLevel, timer;
  16. int windowX=30;
  17. int windowY=50;
  18. boolean connected=false;
  19. String serialPort;

  20. void settings() {
  21.   size(1000, 600);
  22. }

  23. void setup() {
  24.   background(0);
  25.   surface.setResizable(true);
  26.   frameRate(50);
  27. }

  28. void draw() {
  29.   windowWidth=width-100;
  30.   windowHeight=height-100;
  31.   if (!connected) {
  32.     background(0, 0, 0);
  33.     text("ARDUINO OSCILLOSCOPE\n\nSelect serial port:", 25, 25);
  34.     for (int i=0; i<Serial.list().length; i++)
  35.       text("F"+(i+1)+" - "+Serial.list()[i], 25, 80+i*20);
  36.   } else {
  37.     background(0, 0, 0);

  38.     // update frequency counters every second
  39.     loopCounter++;
  40.     if (loopCounter>frameRate) {  
  41.       loopCounter=0;
  42.       float elapsedSeconds=(millis()-timer)/1000;
  43.       timer=millis();
  44.       sps=(writeIndex-prevWriteIndex)/elapsedSeconds;  // sample rate
  45.       if (sps<0)sps+=bufferSize;
  46.       prevWriteIndex=writeIndex;
  47.       frequency=trigCounter/elapsedSeconds;            // signal frequency
  48.       trigCounter=0;
  49.     }
  50. /*
  51.     // read switch position & set voltage range
  52.     boolean switch1=((buffer[writeIndex*2]&(byte)8)==8);                                                
  53.     boolean switch2=((buffer[writeIndex*2]&(byte)4)==4);
  54.     if (!switch1&&!switch2) voltageRange=20;
  55.     if (!switch1&&switch2) voltageRange=10;
  56.     if (switch1&&!switch2) voltageRange=6.64;
  57.     if (switch1&&switch2) voltageRange=5;
  58. */
  59. voltageRange=5;

  60.     // print voltage scale
  61.     for (int n=0; n<=10; n++)                                                                           
  62.       text(nf(voltageRange/10*n, 2, 2)+"V", windowX+windowWidth+5, windowY+windowHeight-(n*windowHeight/10));

  63.     // print interface and statistics
  64.     text("[F1-F2] ZOOM | [F3] SYNC: "+sync+" | [F4] HOLD: "+hold+" | [F5-F6] TRIG LPF | [F7-F8] PRESCALER: "+nf((pow(2, prescaler)), 1, 0)+" | [<--->] OFFSET", 25, 25);
  65.     text("frequency: "+nf(frequency, 5, 2)+"Hz"
  66.       +" | average DCV: "+nf(trigLevel/256*voltageRange, 2, 2)+"V"
  67.       +" | samplerate: "+nf(sps, 5, 2)+"Hz"
  68.       +" | samples per line: "+samplesPerLine
  69.       +" | division: "+samplesPerLine/sps*(float)width*100+"ms", 25, height-20);

  70.     // draw trigLevel (= average voltage) line
  71.     stroke(0, 0, 100);                                                                                   
  72.     int trigLevelHeight=(int)(trigLevel*(float)windowHeight/256);
  73.     line(windowX, windowY+windowHeight-trigLevelHeight, windowX+windowWidth, windowY+windowHeight-trigLevelHeight);  

  74.     // draw grid
  75.     stroke(50);                                                                                          
  76.     for (float n=0; n<=windowWidth; n+=(float)windowWidth/10)
  77.       line(n+windowX, windowY, n+windowX, windowHeight+windowY);
  78.     for (float n=0; n<=windowHeight; n+=(float)windowHeight/10)
  79.       line(windowX, n+windowY, windowX+windowWidth, n+windowY);

  80.     // ------------------------------
  81.     // DRAW WAVEFORM
  82.     // ------------------------------
  83.     stroke(255);
  84.     float prevSampleValue=0;
  85.     if (sync) readIndex=trigIndex;                               // sync: start reading from last trig position
  86.     if (!sync) readIndex=writeIndex;                             // no sync: start reading from last sample we received
  87.     readIndex+=offset;
  88.     float lineIncr=(float)1/samplesPerLine;
  89.     if (lineIncr<1) lineIncr=1;
  90.     for (float line=0; line<windowWidth; line+=lineIncr) {                                          // cycle screen lines (from right to left)
  91.       float sampleValue=(float)getValueFromBuffer((int)((float)readIndex-line*samplesPerLine));     // get the value for the screen line
  92.       sampleValue*=(float)windowHeight/256;                                                        // scale to windowHeight
  93.       if (line>0)
  94.         line(windowX+windowWidth-line,
  95.           windowY+windowHeight-prevSampleValue,
  96.           windowX+windowWidth-line-lineIncr,
  97.           windowY+windowHeight-sampleValue);
  98.       prevSampleValue=sampleValue;
  99.     }

  100.     // ------------------------------
  101.     // BUFFER INCOMING BYTES & TRIG
  102.     // ------------------------------
  103.     if (hold) {
  104.       serial.clear();                                                                                      // HOLD: don't receive samples; clear serial buffer
  105.     } else {
  106.       while (serial.available ()>0) {                                                                      // RUN: receive samples
  107.         writeIndex++;  
  108.         if (writeIndex>=bufferSize) writeIndex=0;                                                          // handle overflow
  109.         //buffer[writeIndex+writeIndex]=(byte)serial.read();                                                 // add 1 sample (2 bytes) to buffer
  110.         buffer[writeIndex]=(byte)serial.read();                                                 // add 1 sample (2 bytes) to buffer
  111.      //   buffer[writeIndex+writeIndex+1]=(byte)serial.read();
  112.         trigLevel=trigLevel*(1-trigLevelLPF)+(float)getValueFromBuffer(writeIndex)*trigLevelLPF;           // level for trigger intersection = exponential moving average of voltage
  113.         if (getValueFromBuffer(writeIndex)>=trigLevel&& getValueFromBuffer(writeIndex-1)<trigLevel) {      // rising intersect detected
  114.           trigIndex=writeIndex;                                                                            // set trigIndex (index of buffer that corresponds to last trig)
  115.           trigCounter++;                                                                                   // count trigs (to calculate the frequency)
  116.         }
  117.       }
  118.     }
  119.   }
  120. }


  121. // Read value from buffer
  122. int getValueFromBuffer(int index) {                                                                     
  123.   while (index<0) index+=bufferSize;                                                                       // handle overflow of circular buffer
  124. //  return((buffer[index*2]&3)<<8 | buffer[index*2+1]&0xff);                                                 // convert bytes to int
  125.   return(buffer[index]&0xff);                                                 // convert bytes to int
  126. }

  127. // Handle keys
  128. void keyPressed() {  
  129.   if (key == CODED) {
  130.     if (connected) {
  131.       if (keyCode == KeyEvent.VK_F1) {
  132.         samplesPerLine*=1.1;
  133.         if (samplesPerLine*windowWidth>bufferSize) samplesPerLine=bufferSize/windowWidth;
  134.       }
  135.       if (keyCode == KeyEvent.VK_F2) {
  136.         samplesPerLine/=1.1;
  137.         if (samplesPerLine<1/(float)windowWidth) samplesPerLine=1/(float)windowWidth;
  138.       }
  139.       if (keyCode == KeyEvent.VK_F3) {
  140.         sync=!sync;
  141.       }
  142.       if (keyCode == KeyEvent.VK_F4) {
  143.         hold=!hold;
  144.       }
  145.       if (keyCode == KeyEvent.VK_F5) {
  146.         if (trigLevelLPF<.01) trigLevelLPF*=10;
  147.       }
  148.       if (keyCode == KeyEvent.VK_F6) {
  149.         if (trigLevelLPF>.000001) trigLevelLPF/=10;
  150.       }
  151.       if (keyCode == KeyEvent.VK_F7) {
  152.         if (prescaler>3) prescaler--;
  153.         serial.write((byte)prescaler);
  154.       }
  155.       if (keyCode == KeyEvent.VK_F8) {
  156.         if (prescaler<7) prescaler++;
  157.         serial.write((byte)prescaler);
  158.       }
  159.       if (keyCode == LEFT) {
  160.         offset-=samplesPerLine*20;
  161.         if (offset<-bufferSize) offset=-bufferSize;
  162.       }
  163.       if (keyCode == RIGHT) {
  164.         offset+=samplesPerLine*20;
  165.         if (offset>0) offset=0;
  166.       }
  167.     } else {
  168.       serial = new Serial(this, Serial.list()[keyCode-112], serialBaudRate);
  169.       serial.write((byte)prescaler);
  170.       connected=true;
  171.     }
  172.   }
  173. }
复制代码


回复

使用道具 举报

 楼主| 发表于 昨天 09:40 | 显示全部楼层
另一個初學型示波器範例:
Arduino - Oscilloscope (poor Man's Oscilloscope)
https://www.instructables.com/id ... -mans-Oscilloscope/

  1. // Oscilloscope
  2. // Input defined by ANALOG_IN
  3. // SIG_OUT true puts a 2kHz wave on DIGITAL_OUT for testing.

  4. #define ANALOG_IN 0
  5. #define DIGITAL_OUT 13
  6. bool SIG_OUT = true;

  7. void setup() {
  8.   analogReadResolution(10);
  9.   Serial.begin(9600);
  10.   //Serial.begin(115200);

  11.   // Generate a signal to examine (testing)
  12.   if (SIG_OUT) {
  13.     pinMode(DIGITAL_OUT, OUTPUT);

  14.     // initialize timer1
  15.     noInterrupts();           // disable all interrupts
  16.     TCCR1A = 0;
  17.     TCCR1B = 0;
  18.     TCNT1  = 0;

  19.     OCR1A = 31250;            // compare match register 16MHz/256/2Hz
  20.     TCCR1B |= (1 << WGM12);   // CTC mode
  21.     TCCR1B |= (1 << CS12);    // 256 prescaler
  22.     TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
  23.     interrupts();             // enable all interrupts
  24.   }
  25. }

  26. // Interrupt based
  27. ISR(TIMER1_COMPA_vect) {
  28.   digitalWrite(DIGITAL_OUT, digitalRead(DIGITAL_OUT) ^ 1);   // Toggle
  29. }

  30. void loop() {
  31.   int val = analogRead(ANALOG_IN);
  32.   Serial.write( 0xff );
  33.   Serial.write( (val >> 8) & 0xff );
  34.   Serial.write( val & 0xff );
  35. }
复制代码


配合使用的Processing程序:
  1. /*
  2. * Oscilloscope
  3. * Gives a visual rendering of analog pin in realtime.
  4. *
  5. * ---------------- IMPROVEMENTS ------------------
  6. * Updates by John Porter, 2/7/2014
  7. * Added ability to move waveform left or right.
  8. * Added gridlines (bounds and minor).
  9. * Added ability to pause/resume.
  10. * Added ability to measure time.
  11. * General usability improvements.
  12. *
  13. * --------------- ORIGINAL PROJECT ---------------
  14. * This project is part of Accrochages
  15. * See http://accrochages.drone.ws
  16. * (c) 2008 Sofian Audry (info@sofianaudry.com)
  17. * ------------------------------------------------
  18. *
  19. * This program is free software: you can redistribute it and/or modify
  20. * it under the terms of the GNU General Public License as published by
  21. * the Free Software Foundation, either version 3 of the License, or
  22. * (at your option) any later version.
  23. *
  24. * This program is distributed in the hope that it will be useful,
  25. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  27. * GNU General Public License for more details.
  28. *
  29. * You should have received a copy of the GNU General Public License
  30. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  31. */

  32. // * ------------------ HOT KEYS ------------------
  33. final char T_UP       = 'w'; // Translate waveform up
  34. final char T_DOWN     = 's'; //                    down
  35. final char T_LEFT     = 'a'; //                    left
  36. final char T_RIGHT    = 'd'; //                    right
  37. final char Z_IN       = 'c'; // Horizontal zoom in
  38. final char Z_OUT      = 'z'; //                 out
  39. final char S_IN       = 'e'; // Vertical scale in
  40. final char S_OUT      = 'q'; //                out
  41. final char MGL_UP     = 'r'; // Minor grid lines increase
  42. final char MGL_DOWN   = 'f'; //                  decrease
  43. final char TOG_PAUSE  = 'p'; // Toggle pause (unpause resets waveform)
  44. final char RESET_AXIS = ' '; // Reset axis settings
  45. final char MEAS_TIME  = 'x'; // Adds and/or highlights vertical bars (time measurement)
  46. final char BAR_LEFT   = ','; // Move highlighted vertical bar left (can also mouse click)
  47. final char BAR_RIGHT  = '.'; //                               right
  48. // * ----------------------------------------------

  49. // * --------------- STARTING STATE ---------------
  50. float zoom    = 1.0;
  51. float scale   = 0.5;
  52. int centerV   = 0;
  53. int centerH   = 0;
  54. int gridLines = 0;
  55. int com_port  = 0;   // Index number in Serial.list
  56. // * ----------------------------------------------

  57. // Global vars
  58. import processing.serial.*;
  59. Serial port;                    // Create object from Serial class
  60. int val;                        // Data received from the serial port
  61. long valTime;                   // Time data was received
  62. int[] values;
  63. long[] times;
  64. float voltage;
  65. float measTime = 0;
  66. int   timeMode = 0;
  67. int[] timeBars = {0, 0};
  68. PFont f;
  69. boolean pause;

  70. // Setup
  71. void setup() {
  72.   size(1280, 480);
  73.   port = new Serial(this, Serial.list()[com_port], 9600);    // Com port specified here
  74.   values = new int[width];
  75.   times = new long[width];
  76.   timeBars[0] = width/3;
  77.   timeBars[1] = 2*width/3;
  78.   pause = false;
  79.   smooth();
  80.   f = createFont("Arial", 16, true);
  81. }

  82. // Read value from serial stream
  83. int getValue() {
  84.   int value = -1;
  85.   while (port.available () >= 3) {
  86.     if (port.read() == 0xff) {
  87.       value = (port.read() << 8) | (port.read());
  88.     }
  89.   }
  90.   return value;
  91. }

  92. // Get a y-value for the datapoint, varies based on axis settings
  93. int getY(int val) {
  94.   return (int)(height/2 -(val-512+centerV)*scale / 1023.0f * (height - 1));
  95. }

  96. // Push the values in the data array
  97. void pushValue(int value) {
  98.   for (int i=0; i<width-1; i++)
  99.     values[i] = values[i+1];
  100.   values[width-1] = value;
  101. }

  102. // Push the timestamps in the time array
  103. void pushTime(long time) {
  104.   for (int i=0; i<width-1; i++)
  105.     times[i] = times[i+1];
  106.   times[width-1] = time;
  107. }

  108. // Draw waveform
  109. void drawLines() {
  110.   int x0 = 0, x1 = 0, y0 = 0, y1 = 0;
  111.   stroke(255,255,0);
  112.   for (int i=0; i<width; i++) {
  113.     x1 = round(width - ((width-i) * zoom) + centerH);
  114.     y1 = getY(values[i]);
  115.     if(i > 1)
  116.       line(x0, y0, x1, y1);
  117.     x0 = x1;
  118.     y0 = y1;
  119.   }
  120. }

  121. // Draw gridlines (bounds, minor)
  122. void drawGrid() {
  123.   // Get scaled values for bounds
  124.   int pFive = getY(1023);
  125.   int zero  = getY(0);

  126.   // Draw voltage bounds
  127.   stroke(255, 0, 0);
  128.   line(0, pFive-1, width, pFive-1);
  129.   line(0, zero+1, width, zero+1);

  130.   // Add voltage bound text
  131.   textFont(f, 10);
  132.   fill(255, 0, 0);
  133.   text("+5V", 5, pFive+12);
  134.   text(" 0V", 5, zero-4);

  135.   // Draw minor grid lines
  136.   int gridVal = 0;
  137.   stroke(75, 75, 75);
  138.   for (int i = 0; i < gridLines; i++) {
  139.     gridVal = getY(round((i+1.0)*(1023.0 / (gridLines+1.0))));
  140.     line(0, gridVal, width, gridVal);
  141.   }

  142.   // Add minor grid line text
  143.   if (gridLines > 0) {
  144.     textFont(f, 16);
  145.     fill(204, 102, 0);
  146.     float scaleVal = truncate(5.0f / (gridLines+1), 3);
  147.     text("Grid: " + scaleVal + "V", 1170, height-12);
  148.   }
  149.   
  150.   // Print difference between vertical 'time' bars
  151.   if (timeMode > 0) {
  152.     textFont(f, 16);
  153.     fill(204, 102, 0);
  154.    
  155.     int idx0 = round(width + (timeBars[0] - width - centerH)/zoom);
  156.     int idx1 = round(width + (timeBars[1] - width - centerH)/zoom);
  157.    
  158.     // Ensure time bars are over a recorded portion of the waveform
  159.     if(idx1 < 0 || idx0 < 0 || idx1 > (width-1) || idx0 > (width-1) || times[idx1] == 0 || times[idx0] == 0)
  160.       text("Time: N/A", 30, height-12);
  161.     else{
  162.       float timeDiff = truncate((times[idx1] - times[idx0])/2000000.0,2);
  163.       text("Time: " + timeDiff + "ms", 30, height-12);
  164.     }
  165.   }
  166. }

  167. // Draw vertical 'time bars' (seperate from above for better layering)
  168. void drawVertLines(){
  169.   stroke(75, 75, 75);
  170.   if (timeMode == 1) {
  171.     line(timeBars[1], 0, timeBars[1], height);
  172.     stroke(100, 100, 255);
  173.     line(timeBars[0], 0, timeBars[0], height);
  174.   }
  175.   else if (timeMode == 2) {
  176.     line(timeBars[0], 0, timeBars[0], height);
  177.     stroke(100, 255, 100);
  178.     line(timeBars[1], 0, timeBars[1], height);
  179.   }
  180. }

  181. // Truncate a floating point number
  182. float truncate(float x, int digits) {
  183.   float temp = pow(10.0, digits);
  184.   return round( x * temp ) / temp;
  185. }

  186. // When a key is pressed down or held...
  187. void keyPressed() {
  188.   switch (key) {
  189.   case T_UP: centerV += 10/scale; break;                     // Move waveform up
  190.   case T_DOWN: centerV -= 10/scale; break;                   // Move waveform down
  191.   case T_RIGHT: centerH += 10/scale; break;                  // Move waveform right
  192.   case T_LEFT: centerH -= 10/scale; break;                   // Move waveform left
  193.   case MGL_UP:                                               // Increase minor grid lines
  194.     if (gridLines < 49)
  195.       gridLines += 1;
  196.     break;
  197.   case MGL_DOWN:                                             // Decrease minor grid lines
  198.     if (gridLines > 0)
  199.       gridLines -= 1;
  200.     break;
  201.   case BAR_LEFT:                                             // Move the time bar left (also mouse click)
  202.     if (timeMode == 1 && timeBars[0] > 0)
  203.       timeBars[0] -= 1;
  204.     else if (timeMode == 2 && timeBars[1] > 0)
  205.       timeBars[1] -= 1;
  206.     break;
  207.   case BAR_RIGHT:                                            // Move the time bar right (also mouse click)
  208.     if (timeMode == 1 && timeBars[0] < width-1)
  209.       timeBars[0] += 1;
  210.     else if (timeMode == 2 && timeBars[1] < width-1)
  211.       timeBars[1] += 1;
  212.     break;
  213.   }
  214. }

  215. // When a key is released...
  216. void keyReleased() {
  217.   println(key+": "+(int)key);
  218.   switch (key) {
  219.   case Z_IN:                                                 // Zoom horizontal
  220.     zoom *= 2.0f;
  221.     if ( (int) (width / zoom) <= 1 )
  222.       zoom /= 2.0f;
  223.     break;
  224.   case Z_OUT:                                                // Zoom horizontal
  225.     zoom /= 2.0f;
  226.     if (zoom < 1.0f)
  227.       zoom *= 2.0f;
  228.     break;
  229.   case S_IN: scale*=2; break;                                // Scale vertical
  230.   case S_OUT: scale /= 2; break;                             // Scale vertical
  231.   case RESET_AXIS:                                           // Reset all scaling
  232.     centerV = 0; centerH = 0;
  233.     scale = 0.5; zoom  = 1; gridLines = 0;
  234.     break;
  235.   case MEAS_TIME: timeMode = (timeMode + 1) % 3; break;      // Change the vertical bars (off, left bar, right bar)
  236.   case TOG_PAUSE:                                            // Toggle waveform pausing
  237.     if (pause) {
  238.       centerH = 0;
  239.       for (int i=0; i<width; i++){
  240.         values[i] = 0;                                       // Clear data on resume
  241.         times[i] = 0;
  242.       }
  243.     }
  244.     pause = !pause;
  245.   }
  246. }

  247. // Use mouse clicks to quickly move vertical bars (if highlighted)
  248. void mousePressed() {
  249.   if(timeMode == 1)
  250.     timeBars[0] = mouseX;
  251.   else if(timeMode == 2)
  252.     timeBars[1] = mouseX;
  253. }

  254. // Primary drawing function
  255. void draw()
  256. {
  257.   background(0);
  258.   drawGrid();
  259.   // Get current voltage, time of reading
  260.   val = getValue();
  261.   valTime = System.nanoTime();
  262.   
  263.   // If not paused
  264.   if (!pause && val != -1) {
  265.     // Push value/time onto array
  266.     pushValue(val);
  267.     pushTime(valTime);
  268.    
  269.     // Print current voltage reading
  270.     textFont(f, 16);
  271.     fill(204, 102, 0);
  272.     voltage = truncate(5.0*val / 1023, 1);
  273.     text("Voltage: " + voltage + "V", 1170, 30);
  274.   }
  275.   drawLines();
  276.   drawVertLines();
  277. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 14:36 | 显示全部楼层
把以上範例改以VUSB代替串口:

Arduino程序:
  1. // Oscilloscope
  2. // Input defined by ANALOG_IN
  3. // SIG_OUT true puts a 2kHz wave on DIGITAL_OUT for testing.

  4. #include <HIDSerial.h>

  5. HIDSerial serial;

  6. #define ANALOG_IN 0
  7. #define DIGITAL_OUT 13
  8. bool SIG_OUT = true;

  9. void setup() {
  10.   analogReadResolution(8); //use 1-byte A/D
  11.   serial.begin(); //HID

  12.   //Serial.begin(9600);
  13.   //Serial.begin(115200);

  14.   // Generate a signal to examine (testing)
  15.   if (SIG_OUT) {
  16.     pinMode(DIGITAL_OUT, OUTPUT);

  17.     // initialize timer1
  18.     noInterrupts();           // disable all interrupts
  19.     TCCR1A = 0;
  20.     TCCR1B = 0;
  21.     TCNT1  = 0;

  22.     OCR1A = 31250;            // compare match register 16MHz/256/2Hz
  23.     TCCR1B |= (1 << WGM12);   // CTC mode
  24.     TCCR1B |= (1 << CS12);    // 256 prescaler
  25.     TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
  26.     interrupts();             // enable all interrupts
  27.   }
  28. }

  29. // Interrupt based
  30. ISR(TIMER1_COMPA_vect) {
  31.   digitalWrite(DIGITAL_OUT, digitalRead(DIGITAL_OUT) ^ 1);   // Toggle
  32. }

  33. //byte val = 0;
  34. void loop() {
  35.   byte val = analogRead(ANALOG_IN);
  36. /*
  37.     Serial.write( 0xff );
  38.     Serial.write( (val >> 8) & 0xff );
  39.     Serial.write( val & 0xff );
  40.   */
  41.   if (val==0) val=1; //use 1-byte only and reserve 0 for special use
  42.   serial.write( val );
  43.   serial.poll();
  44. }
复制代码


配合使用的Processing程序:
  1. /*
  2. * Oscilloscope
  3. * Gives a visual rendering of analog pin in realtime.
  4. *
  5. * ---------------- IMPROVEMENTS ------------------
  6. * Updates by John Porter, 2/7/2014
  7. * Added ability to move waveform left or right.
  8. * Added gridlines (bounds and minor).
  9. * Added ability to pause/resume.
  10. * Added ability to measure time.
  11. * General usability improvements.
  12. *
  13. * --------------- ORIGINAL PROJECT ---------------
  14. * This project is part of Accrochages
  15. * See http://accrochages.drone.ws
  16. * (c) 2008 Sofian Audry (info@sofianaudry.com)
  17. * ------------------------------------------------
  18. *
  19. * This program is free software: you can redistribute it and/or modify
  20. * it under the terms of the GNU General Public License as published by
  21. * the Free Software Foundation, either version 3 of the License, or
  22. * (at your option) any later version.
  23. *
  24. * This program is distributed in the hope that it will be useful,
  25. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  27. * GNU General Public License for more details.
  28. *
  29. * You should have received a copy of the GNU General Public License
  30. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  31. */

  32. // * ------------------ HOT KEYS ------------------
  33. final char T_UP       = 'w'; // Translate waveform up
  34. final char T_DOWN     = 's'; //                    down
  35. final char T_LEFT     = 'a'; //                    left
  36. final char T_RIGHT    = 'd'; //                    right
  37. final char Z_IN       = 'c'; // Horizontal zoom in
  38. final char Z_OUT      = 'z'; //                 out
  39. final char S_IN       = 'e'; // Vertical scale in
  40. final char S_OUT      = 'q'; //                out
  41. final char MGL_UP     = 'r'; // Minor grid lines increase
  42. final char MGL_DOWN   = 'f'; //                  decrease
  43. final char TOG_PAUSE  = 'p'; // Toggle pause (unpause resets waveform)
  44. final char RESET_AXIS = ' '; // Reset axis settings
  45. final char MEAS_TIME  = 'x'; // Adds and/or highlights vertical bars (time measurement)
  46. final char BAR_LEFT   = ','; // Move highlighted vertical bar left (can also mouse click)
  47. final char BAR_RIGHT  = '.'; //                               right
  48. // * ----------------------------------------------

  49. // * --------------- STARTING STATE ---------------
  50. float zoom    = 1.0;
  51. float scale   = 0.5;
  52. int centerV   = 0;
  53. int centerH   = 0;
  54. int gridLines = 0;
  55. int com_port  = 1;   // Index number in Serial.list
  56. // * ----------------------------------------------

  57. int val;                        // Data received from the serial port
  58. long valTime;                   // Time data was received
  59. int[] values;
  60. long[] times;
  61. float voltage;
  62. float measTime = 0;
  63. int   timeMode = 0;
  64. int[] timeBars = {0, 0};
  65. PFont f;
  66. boolean pause;

  67. /*****************************************************
  68. Host software for HID-class USB serial communication.
  69. It allows connecting to a HID serial device (16c0:05df),
  70. sending (up to 32 bytes per packet) and receiving
  71. strings from the device. The code uses a slightly modified
  72. version of the g4p library for user interface, and the
  73. HIDAPI library for handling HID requests.

  74. The code was initially written by Chaniel Chadowitz
  75. and modified by Ray Wang (Rayshobby LLC). The code is published
  76. under Creative Commons Attribution-ShareAlike 3.0 license.
  77. *************************************************************/
  78. import g4p_controls.*;
  79. import com.codeminders.hidapi.HIDDeviceInfo;
  80. import com.codeminders.hidapi.HIDManager;
  81. import com.codeminders.hidapi.HIDDevice;
  82. import java.io.IOException;
  83. import java.util.List;
  84. import java.util.ArrayList;
  85. import java.util.LinkedList;
  86. import java.awt.Font;

  87. GButton connectButton;

  88. boolean paused;
  89. String serialText = new String();

  90. int VENDOR_ID = 0x16c0;
  91. int PRODUCT_ID = 0x05df;
  92. HIDDevice device = null;
  93. Boolean device_initialized = false;
  94. byte value1 = 0;
  95. int value = 0;

  96. // Setup
  97. void setup() {
  98.   size(1280, 480);
  99.   G4P.setGlobalColorScheme(5);  

  100.   connectButton = new GButton(this, 10, 15, 100, 20, "Connect");
  101.   connectButton.setTextBold();

  102.   device_initialized = false;
  103.   values = new int[width];
  104.   times = new long[width];
  105.   timeBars[0] = width/3;
  106.   timeBars[1] = 2*width/3;
  107.   pause = false;
  108.   smooth();
  109.   f = createFont("Arial", 16, true);
  110. }


  111. // Get a y-value for the datapoint, varies based on axis settings
  112. int getY(int val) {
  113.   return (int)(height/2 -(val-512+centerV)*scale / 1023.0f * (height - 1));
  114. }

  115. // Push the values in the data array
  116. void pushValue(int value) {
  117.   for (int i=0; i<width-1; i++)
  118.     values[i] = values[i+1];
  119.   values[width-1] = value;
  120. }

  121. // Push the timestamps in the time array
  122. void pushTime(long time) {
  123.   for (int i=0; i<width-1; i++)
  124.     times[i] = times[i+1];
  125.   times[width-1] = time;
  126. }

  127. // Draw waveform
  128. void drawLines() {
  129.   int x0 = 0, x1 = 0, y0 = 0, y1 = 0;
  130.   stroke(255, 255, 0);
  131.   for (int i=0; i<width; i++) {
  132.     x1 = round(width - ((width-i) * zoom) + centerH);
  133.     y1 = getY(values[i]*4);
  134.     if (i > 1)
  135.       line(x0, y0, x1, y1);
  136.     x0 = x1;
  137.     y0 = y1;
  138.   }
  139. }

  140. // Draw gridlines (bounds, minor)
  141. void drawGrid() {
  142.   // Get scaled values for bounds
  143.   int pFive = getY(1023);
  144.   int zero  = getY(0);

  145.   // Draw voltage bounds
  146.   stroke(255, 0, 0);
  147.   line(0, pFive-1, width, pFive-1);
  148.   line(0, zero+1, width, zero+1);

  149.   // Add voltage bound text
  150.   textFont(f, 10);
  151.   fill(255, 0, 0);
  152.   text("+5V", 5, pFive+12);
  153.   text(" 0V", 5, zero-4);

  154.   // Draw minor grid lines
  155.   int gridVal = 0;
  156.   stroke(75, 75, 75);
  157.   for (int i = 0; i < gridLines; i++) {
  158.     gridVal = getY(round((i+1.0)*(1023.0 / (gridLines+1.0))));
  159.     line(0, gridVal, width, gridVal);
  160.   }

  161.   // Add minor grid line text
  162.   if (gridLines > 0) {
  163.     textFont(f, 16);
  164.     fill(204, 102, 0);
  165.     float scaleVal = truncate(5.0f / (gridLines+1), 3);
  166.     text("Grid: " + scaleVal + "V", 1170, height-12);
  167.   }

  168.   // Print difference between vertical 'time' bars
  169.   if (timeMode > 0) {
  170.     textFont(f, 16);
  171.     fill(204, 102, 0);

  172.     int idx0 = round(width + (timeBars[0] - width - centerH)/zoom);
  173.     int idx1 = round(width + (timeBars[1] - width - centerH)/zoom);

  174.     // Ensure time bars are over a recorded portion of the waveform
  175.     if (idx1 < 0 || idx0 < 0 || idx1 > (width-1) || idx0 > (width-1) || times[idx1] == 0 || times[idx0] == 0)
  176.       text("Time: N/A", 30, height-12);
  177.     else {
  178.       float timeDiff = truncate((times[idx1] - times[idx0])/2000000.0, 2);
  179.       text("Time: " + timeDiff + "ms", 30, height-12);
  180.     }
  181.   }
  182. }

  183. // Draw vertical 'time bars' (seperate from above for better layering)
  184. void drawVertLines() {
  185.   stroke(75, 75, 75);
  186.   if (timeMode == 1) {
  187.     line(timeBars[1], 0, timeBars[1], height);
  188.     stroke(100, 100, 255);
  189.     line(timeBars[0], 0, timeBars[0], height);
  190.   } else if (timeMode == 2) {
  191.     line(timeBars[0], 0, timeBars[0], height);
  192.     stroke(100, 255, 100);
  193.     line(timeBars[1], 0, timeBars[1], height);
  194.   }
  195. }

  196. // Truncate a floating point number
  197. float truncate(float x, int digits) {
  198.   float temp = pow(10.0, digits);
  199.   return round( x * temp ) / temp;
  200. }


  201. // When a key is pressed down or held...
  202. void keyPressed() {
  203.   switch (key) {
  204.   case T_UP:
  205.     centerV += 10/scale;
  206.     break;                     // Move waveform up
  207.   case T_DOWN:
  208.     centerV -= 10/scale;
  209.     break;                   // Move waveform down
  210.   case T_RIGHT:
  211.     centerH += 10/scale;
  212.     break;                  // Move waveform right
  213.   case T_LEFT:
  214.     centerH -= 10/scale;
  215.     break;                   // Move waveform left
  216.   case MGL_UP:                                               // Increase minor grid lines
  217.     if (gridLines < 49)
  218.       gridLines += 1;
  219.     break;
  220.   case MGL_DOWN:                                             // Decrease minor grid lines
  221.     if (gridLines > 0)
  222.       gridLines -= 1;
  223.     break;
  224.   case BAR_LEFT:                                             // Move the time bar left (also mouse click)
  225.     if (timeMode == 1 && timeBars[0] > 0)
  226.       timeBars[0] -= 1;
  227.     else if (timeMode == 2 && timeBars[1] > 0)
  228.       timeBars[1] -= 1;
  229.     break;
  230.   case BAR_RIGHT:                                            // Move the time bar right (also mouse click)
  231.     if (timeMode == 1 && timeBars[0] < width-1)
  232.       timeBars[0] += 1;
  233.     else if (timeMode == 2 && timeBars[1] < width-1)
  234.       timeBars[1] += 1;
  235.     break;
  236.   }
  237. }

  238. // When a key is released...
  239. void keyReleased() {
  240.   println(key+": "+(int)key);
  241.   switch (key) {
  242.   case Z_IN:                                                 // Zoom horizontal
  243.     zoom *= 2.0f;
  244.     if ( (int) (width / zoom) <= 1 )
  245.       zoom /= 2.0f;
  246.     break;
  247.   case Z_OUT:                                                // Zoom horizontal
  248.     zoom /= 2.0f;
  249.     if (zoom < 1.0f)
  250.       zoom *= 2.0f;
  251.     break;
  252.   case S_IN:
  253.     scale*=2;
  254.     break;                                // Scale vertical
  255.   case S_OUT:
  256.     scale /= 2;
  257.     break;                             // Scale vertical
  258.   case RESET_AXIS:                                           // Reset all scaling
  259.     centerV = 0;
  260.     centerH = 0;
  261.     scale = 0.5;
  262.     zoom  = 1;
  263.     gridLines = 0;
  264.     break;
  265.   case MEAS_TIME:
  266.     timeMode = (timeMode + 1) % 3;
  267.     break;      // Change the vertical bars (off, left bar, right bar)
  268.   case TOG_PAUSE:                                            // Toggle waveform pausing
  269.     if (pause) {
  270.       centerH = 0;
  271.       for (int i=0; i<width; i++) {
  272.         values[i] = 0;                                       // Clear data on resume
  273.         times[i] = 0;
  274.       }
  275.     }
  276.     pause = !pause;
  277.   }
  278. }

  279. // Use mouse clicks to quickly move vertical bars (if highlighted)
  280. void mousePressed() {
  281.   if (timeMode == 1)
  282.     timeBars[0] = mouseX;
  283.   else if (timeMode == 2)
  284.     timeBars[1] = mouseX;
  285. }


  286. // Primary drawing function
  287. void draw() {
  288.   background(0);

  289.   if ( device != null && !paused ) {
  290.     deviceRead();
  291.   }

  292.   drawGrid();
  293.   // Get current voltage, time of reading
  294.   val = value;

  295.   //  valTime = System.nanoTime();

  296.   // If not paused
  297.   if (!pause && val != -1) {
  298.     // Push value/time onto array
  299.     pushValue(val);
  300.     pushTime(valTime);

  301.     // Print current voltage reading
  302.     textFont(f, 16);
  303.     fill(204, 102, 0);
  304.     voltage = truncate(3.3*val / 256, 2);
  305.     text("Voltage: " + voltage + "V", 1170, 30);
  306.   }
  307.   drawLines();
  308.   drawVertLines();
  309. }

  310. public void deviceInitialize() {
  311.   if (!device_initialized) {
  312.     device_initialized = true;
  313.     com.codeminders.hidapi.ClassPathLibraryLoader
  314.       .loadNativeHIDLibrary();
  315.   }
  316. }

  317. public void deviceFindFirst() {
  318.   deviceInitialize();
  319.   HIDDeviceInfo[] infos = deviceFindAllDescriptors();

  320.   if (infos.length > 0) {
  321.     try {
  322.       device = infos[0].open();
  323.     }
  324.     catch (Exception e) {
  325.       device = null;
  326.     }
  327.   }
  328. }

  329. public HIDDeviceInfo[] deviceFindAllDescriptors() {
  330.   deviceInitialize();

  331.   List<HIDDeviceInfo> devlist = new ArrayList<HIDDeviceInfo>();

  332.   try {
  333.     HIDManager hidManager = HIDManager.getInstance();

  334.     HIDDeviceInfo[] infos = hidManager.listDevices();

  335.     for (HIDDeviceInfo info : infos) {
  336.       if (info.getVendor_id() == VENDOR_ID
  337.         && info.getProduct_id() == PRODUCT_ID) {
  338.         devlist.add(info);
  339.       }
  340.     }
  341.   }
  342.   catch (Exception e) {
  343.   }

  344.   return devlist.toArray(new HIDDeviceInfo[devlist.size()]);
  345. }

  346. public void deviceRead() {
  347.   try {
  348.     device.disableBlocking();
  349.     byte[] data = new byte[10];
  350.     int read = device.read(data);
  351.     if (read > 0) {
  352.       for (int i=0; i<read; i++) {
  353.         if (data[i]!=0) {
  354.           value1 = data[i];
  355.           //convert signed byte to unsigned byte
  356.           if (value1 >=0)
  357.           {
  358.             value = value1;
  359.           } else {
  360.             value = int (value1 + 255);
  361.           }
  362.         }
  363.       }
  364.     }
  365.   }
  366.   catch(IOException ioe) {
  367.     //ioe.printStackTrace();
  368.     System.out.println("deviceRead error");
  369.   }
  370. }

  371. public void handleButtonEvents(GButton button, GEvent event) {
  372.   if ( event == GEvent.CLICKED ) {
  373.     if ( button.equals(connectButton) ) {
  374.       if (device!=null) {
  375.         try {
  376.           device.close();
  377.         }
  378.         catch (IOException ioe) {
  379.           ioe.printStackTrace();
  380.         }
  381.         device = null;
  382.         connectButton.setText("Connect");
  383.         connectButton.setTextBold();
  384.         value = 0;
  385.       } else {
  386.         deviceFindFirst();
  387.         connectButton.setText("Disconnect");
  388.         connectButton.setTextBold();
  389.       }
  390.     }
  391.   }
  392. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 14:38 | 显示全部楼层
以上的範例的實用性不大,但可作程序操練之用!
回复 支持 反对

使用道具 举报

发表于 昨天 15:31 | 显示全部楼层
有高清无码大图嘛
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊 ( 浙ICP备09023225号 )

GMT+8, 2019-1-17 05:20 , Processed in 0.051533 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表