Auteur Sujet: un oscilloscope "pas chère" ?  (Lu 344 fois)

gaston

  • Full Member
  • ***
  • Messages: 212
    • Voir le profil
  • 3d printer: core X Y bois "maison"
  • buying date: 03.03.014
  • region/departement: yvelines (78)
un oscilloscope "pas chère" ?
« le: 02 septembre, 2016, 12:36:46 am »
Coucou,

si vous avez besoin de mesurer un signal (en courant continu et <5V) et que vous avez un combo "RAMPS Arduino et grand ecran LCD"
Vous avez ce qu'il faut ;)

Vous devez retirer les pololus, les cavaliers, les différentes sonde et les endstop  (le plus simple est d'avoir une Ramps + Arduino d'avance :p )
Ensuite, on ouvre un nouveau projet Arduino, et on colle le code suivant:

#include "U8glib.h"
#include <EEPROM.h>

// Variables you might want to play with
byte useThreshold = 1;                  // 0 = Off, 1 = Rising, 2 = Falling
byte theThreshold = 128;                // 0-255, Multiplied by voltageConst
unsigned int timePeriod = 200;          // 0-65535, us or ms per measurement (max 0.065s or 65.535s)
byte voltageRange = 1;                  // 1 = 0-3.3V, 2 = 0-1.65V, 3 = 0-0.825V
byte ledBacklight = 100;

boolean autoHScale = true;             // Automatic horizontal (time) scaling
boolean linesNotDots = true;            // Draw lines between data points

// Variables that can probably be left alone
const byte vTextShift = 3;              // Vertical text shift (to vertically align info)
const byte numOfSamples = 100;          // Leave at 100 for 128x64 pixel display
unsigned int HQadcReadings[numOfSamples];
byte adcReadings[numOfSamples];
byte thresLocation = 0;                 // Threshold bar location
float voltageConst = 0.052381;          // Scaling factor for converting 0-63 to V
float avgV = 0.0;   
float maxV = 0.0;
float minV = 0.0;
float ptopV = 0.0;
float theFreq = 0;

const byte theAnalogPin = A0;             // Data read pin

const byte lcdLED = 6;                   // LED Backlight
const byte lcdA0 = A0;                    // pin "X Stepper" on RAMPS for A0 (probe)
const byte lcdRESET = 8;                 // Low reset /
const byte lcdCS = 9;                    // SPI Chip Select (internally pulled up), active low /overide for RAMPS
const byte lcdMOSI = 11;                 // SPI Data transmission /overide for RAMPS
const byte lcdSCK = 13;                  // SPI Serial Clock /overide for RAMPS

// SW SPI:
//U8GLIB_MINI12864_2X u8g(lcdSCK, lcdMOSI, lcdCS, lcdA0, lcdRESET);
// HW SPI:
U8GLIB_ST7920_128X64_4X u8g(23, 17, 16); // Replace for RAMPS, original values:  SCK =13, MOSI = 11, CS =  11

// High speed ADC code
// From: http://forum.arduino.cc/index.php?PHPSESSID=e21f9a71b887039092c91a516f9b0f36&topic=6549.15
#define FASTADC 1
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void collectData(void) {
  unsigned int tempThres = 0;
  unsigned int i = 0;

  if (autoHScale == true) {
    // With automatic horizontal (time) scaling enabled,
    // scale quickly if the threshold location is far, then slow down
    if (thresLocation > 5*numOfSamples/8) {
      timePeriod = timePeriod + 10;
    } else if (thresLocation < 3*numOfSamples/8) {
      timePeriod = timePeriod - 10;
    } else if (thresLocation > numOfSamples/2) {
      timePeriod = timePeriod + 2;
    } else if (thresLocation < numOfSamples/2) {
      timePeriod = timePeriod - 2;
    }
  }
  // Enforce minimum time periods
  if (timePeriod < 35) {
    timePeriod = 35;
  }
 
  // Adjust voltage constant to fit the voltage range
  if (voltageRange == 1) {
//    voltageConst = 0.0523810; // 0-3.30V
      voltageConst = 0.1024; // 0-5V
  } else if (voltageRange == 2) {
    voltageConst = 0.0261905; // 0-1.65V
  } else if (voltageRange == 3) {
    voltageConst = 0.0130952; //0-0.825V
  }
 
  // If using threshold, wait until it has been reached
  if (voltageRange == 1) tempThres = theThreshold << 2;
  else if (voltageRange == 2) tempThres = theThreshold << 1;
  else if (voltageRange == 3) tempThres = theThreshold;
  if (useThreshold == 1) {
     i = 0; while ((analogRead(theAnalogPin)>tempThres) && (i<32768)) i++;
     i = 0; while ((analogRead(theAnalogPin)<tempThres) && (i<32768)) i++;
  }
  else if (useThreshold == 2) {
     i = 0; while ((analogRead(theAnalogPin)<tempThres) && (i<32768)) i++;
     i = 0; while ((analogRead(theAnalogPin)>tempThres) && (i<32768)) i++;
  }

  // Collect ADC readings
  for (i=0; i<numOfSamples; i++) {
    // Takes 35 us with high speed ADC setting
    HQadcReadings[i] = analogRead(theAnalogPin);
    if (timePeriod > 35)
      delayMicroseconds(timePeriod-35);
  }
  for (i=0; i<numOfSamples; i++) {
    // Scale the readings to 0-63 and clip to 63 if they are out of range.
    if (voltageRange == 1) {
      if (HQadcReadings[i]>>4 < 0b111111) adcReadings[i] = HQadcReadings[i]>>4 & 0b111111;
      else adcReadings[i] = 0b111111;
    } else if (voltageRange == 2) {
      if (HQadcReadings[i]>>3 < 0b111111) adcReadings[i] = HQadcReadings[i]>>3 & 0b111111;
      else adcReadings[i] = 0b111111;
    } else if (voltageRange == 3) {
      if (HQadcReadings[i]>>2 < 0b111111) adcReadings[i] = HQadcReadings[i]>>2 & 0b111111;
      else adcReadings[i] = 0b111111;
    }
    // Invert for display
    adcReadings[i] = 63-adcReadings[i];
  }
 
  // Calculate and display frequency of signal using zero crossing
  if (useThreshold != 0) {
     if (useThreshold == 1) {
        thresLocation = 1;
        while ((adcReadings[thresLocation]<(63-(theThreshold>>2))) && (thresLocation<numOfSamples-1)) (thresLocation++);
        thresLocation++;
        while ((adcReadings[thresLocation]>(63-(theThreshold>>2))) && (thresLocation<numOfSamples-1)) (thresLocation++);
     }
     else if (useThreshold == 2) {
        thresLocation = 1;
        while ((adcReadings[thresLocation]>(63-(theThreshold>>2))) && (thresLocation<numOfSamples-1)) (thresLocation++);
        thresLocation++;
        while ((adcReadings[thresLocation]<(63-(theThreshold>>2))) && (thresLocation<numOfSamples-1)) (thresLocation++);
     }

     theFreq = (float) 1000/(thresLocation * timePeriod) * 1000;
  }
 
  // Average Voltage
  avgV = 0;
  for (i=0; i<numOfSamples; i++)
     avgV = avgV + adcReadings[i];
  avgV = (63-(avgV / numOfSamples)) * voltageConst;

  // Maximum Voltage
  maxV = 63;
  for (i=0; i<numOfSamples; i++)
     if (adcReadings[i]<maxV) maxV = adcReadings[i];
  maxV = (63-maxV) * voltageConst;

  // Minimum Voltage
  minV = 0;
  for (i=0; i<numOfSamples; i++)
     if (adcReadings[i]>minV) minV = adcReadings[i];
  minV = (63-minV) * voltageConst;

  // Peak-to-Peak Voltage
  ptopV = maxV - minV;
}

void handleSerial(void) {
  char inByte;
  char dataByte;
  boolean exitLoop = false;
  do {
    // Clear out buffer
    do {
      inByte = Serial.read();
    } while (Serial.available() > 0);
 
    Serial.print("\nArduino LCD Oscilloscope\n");
    Serial.print(" 1 - Change threshold usage (currently: ");
      if (useThreshold == 0) Serial.print("Off)\n");
      else if (useThreshold == 1) Serial.print("Rise)\n");
      else if (useThreshold == 2) Serial.print("Fall)\n");
    Serial.print(" 2 - Change threshold value (currently: ");
      Serial.print(theThreshold, DEC); Serial.print(")\n");
    Serial.print(" 3 - Change sampling period (currently: ");
      Serial.print(timePeriod, DEC); Serial.print(")\n");
    Serial.print(" 4 - Change voltage range (currently: ");
      if (voltageRange == 1) Serial.print("0-3.3V)\n");
      else if (voltageRange == 2) Serial.print("0-1.65V)\n");
      else if (voltageRange == 3) Serial.print("0-0.825V)\n");
    Serial.print(" 5 - Toggle auto horizontal (time) scaling (currently: ");
      if (autoHScale == true) Serial.print("On)\n");
      else if (autoHScale == false) Serial.print("Off)\n");
    Serial.print(" 6 - Toggle line/dot display (currently: ");
      if (linesNotDots == true) Serial.print("Lines)\n");
      else if (linesNotDots == false) Serial.print("Dots)\n");
    Serial.print(" 8 - Exit\n");
   
    // Wait for input/response, refresh display while in menu
    do {
      collectData();
      // Picture Display Loop
      u8g.firstPage(); 
      do { draw(); } while( u8g.nextPage() );
    } while (Serial.available() == 0);
    inByte = Serial.read();
   
    if (inByte == '1') {
      Serial.print("Change threshold usage\n");
      Serial.print(" 0 - Off\n");
      Serial.print(" 1 - Rise\n");
      Serial.print(" 2 - Fall\n");
      do { } while (Serial.available() == 0);
      dataByte = Serial.read();
      if (dataByte == '0') useThreshold = 0;
      else if (dataByte == '1') useThreshold = 1;
      else if (dataByte == '2') useThreshold = 2;
    } else if (inByte == '2') {
      Serial.print("Change threshold value (thresholds for 0-3.3V,0-1.65V,0-0.825V ranges)\n");
      Serial.print(" 0 - 32 (0.41V, 0.21V, 0.10V)\n");
      Serial.print(" 1 - 80 (1.04V, 0.52V, 0.26V)\n");
      Serial.print(" 2 - 128 (1.66V, 0.83V, 0.41V)\n");
      Serial.print(" 3 - 176 (2.28V, 1.14V, 0.57V)\n");
      Serial.print(" 4 - 224 (2.90V, 1.45V, 0.72V)\n");
      do { } while (Serial.available() == 0);
      dataByte = Serial.read();
      if (dataByte == '0') theThreshold = 32;
      else if (dataByte == '1') theThreshold = 80;
      else if (dataByte == '2') theThreshold = 128;
      else if (dataByte == '3') theThreshold = 176;
      else if (dataByte == '4') theThreshold = 224;
    } else if (inByte == '3') {
      Serial.print("Change sampling frequency\n");
      Serial.print(" 0 - 28 kHz (35 us/sample)\n");
      Serial.print(" 1 - 20 kHz (50 us/sample)\n");
      Serial.print(" 2 - 10 kHz (100 us/sample)\n");
      Serial.print(" 3 - 5 kHz (200 us/sample)\n");
      Serial.print(" 4 - 2.5 kHz (400 us/sample)\n");
      do { } while (Serial.available() == 0);
      dataByte = Serial.read();
      if (dataByte == '0') timePeriod = 35;
      else if (dataByte == '1') timePeriod = 50;
      else if (dataByte == '2') timePeriod = 100;
      else if (dataByte == '3') timePeriod = 200;
      else if (dataByte == '4') timePeriod = 400;
    } else if (inByte == '4') {
      Serial.print("Change voltage range\n");
      Serial.print(" 1 - 0-3.3V\n");
      Serial.print(" 2 - 0-1.65V\n");
      Serial.print(" 3 - 0-0.825V\n");
      do { } while (Serial.available() == 0);
      dataByte = Serial.read();
      if (dataByte == '1') voltageRange = 1;
      else if (dataByte == '2') voltageRange = 2;
      else if (dataByte == '3') voltageRange = 3;
    } else if (inByte == '5') {
      Serial.print("Toggle auto horizontal (time) scaling\n");
      Serial.print(" 0 - Off\n");
      Serial.print(" 1 - On\n");
      do { } while (Serial.available() == 0);
      dataByte = Serial.read();
      if (dataByte == '0') autoHScale = false;
      else if (dataByte == '1') autoHScale = true;
    } else if (inByte == '6') {
      Serial.print("Toggle line/dot display\n");
      Serial.print(" 0 - Lines\n");
      Serial.print(" 1 - Dots\n");
      do { } while (Serial.available() == 0);
      dataByte = Serial.read();
      if (dataByte == '0') linesNotDots = true;
      else if (dataByte == '1') linesNotDots = false;
    } else if (inByte == '8') {
      Serial.print("Bye!\n");
      exitLoop = true;
    }
  } while (exitLoop == false);
}

void draw(void) {
  int i;
  char buffer[16];
 
  u8g.setFont(u8g_font_micro);
 
  // Draw static text
  u8g.drawStr(0, 5+vTextShift, "Av");
  u8g.drawStr(0, 11+vTextShift, "Mx");
  u8g.drawStr(0, 17+vTextShift, "Mn");
  u8g.drawStr(0, 23+vTextShift, "PP");
  u8g.drawStr(0, 29+vTextShift, "Th");
  u8g.drawStr(24, 35+vTextShift, "V");
  u8g.drawStr(0, 41+vTextShift, "Tm");
  u8g.drawStr(4, 47+vTextShift, "ms/div");
  u8g.drawStr(20, 53+vTextShift, "Hz");
  u8g.drawStr(0, 59+vTextShift, "R");
 
  // Draw dynamic text
  if (autoHScale == true) u8g.drawStr(124, 5, "A");
  dtostrf(avgV, 3, 2, buffer);
  u8g.drawStr(12, 5+vTextShift, buffer);
  dtostrf(maxV, 3, 2, buffer);
  u8g.drawStr(12, 11+vTextShift, buffer);
  dtostrf(minV, 3, 2, buffer);
  u8g.drawStr(12, 17+vTextShift, buffer);
  dtostrf(ptopV, 3, 2, buffer);
  u8g.drawStr(12, 23+vTextShift, buffer);
  dtostrf(theFreq, 5, 0, buffer);
  u8g.drawStr(0, 53+vTextShift, buffer);
  if (useThreshold == 0) {
    u8g.drawStr(12, 29+vTextShift, "Off");
  } else if (useThreshold == 1) {
    u8g.drawStr(12, 29+vTextShift, "Rise");
    dtostrf((float) (theThreshold>>2) * voltageConst, 3, 2, buffer);
  } else if (useThreshold == 2) {
    u8g.drawStr(12, 29+vTextShift, "Fall");
    dtostrf((float) (theThreshold>>2) * voltageConst, 3, 2, buffer);
  }
  u8g.drawStr(8, 35+vTextShift, buffer);
  // Correctly format the text so that there are always 4 characters
  if (timePeriod < 400) {
    dtostrf((float) timePeriod/1000 * 25, 3, 2, buffer);
  } else if (timePeriod < 4000) {
    dtostrf((float) timePeriod/1000 * 25, 3, 1, buffer);
  } else if (timePeriod < 40000) {
    dtostrf((float) timePeriod/1000 * 25, 3, 0, buffer);
  } else { // Out of range
    dtostrf((float) 0.00, 3, 2, buffer);
  }
  u8g.drawStr(12, 41+vTextShift, buffer);
  if (voltageRange == 1) {
    u8g.drawStr(4, 59+vTextShift, "0-3.30");
  } else if (voltageRange == 2) {
    u8g.drawStr(4, 59+vTextShift, "0-1.65");
  } else if (voltageRange == 3) {
    u8g.drawStr(4, 59+vTextShift, "0-0.83");
  }
 
  // Display graph lines
  u8g.drawLine((128-numOfSamples),0,(128-numOfSamples),63);
  if (useThreshold != 0)
     for (i=29; i<127; i+=3)
        u8g.drawPixel(i,63-(theThreshold>>2));
  for (i=0; i<63; i+=5) {
     u8g.drawPixel(53,i);
     u8g.drawPixel(78,i);
     u8g.drawPixel(103,i);
     u8g.drawPixel(127,i);
  }
  // Threshold bar
  for (i=0; i<63; i+=3)
     u8g.drawPixel(thresLocation+(128-numOfSamples),i);
  // Draw ADC readings
  if (linesNotDots == true) {
    for (i=1; i<numOfSamples; i++) // Draw using lines
      u8g.drawLine(i+(128-numOfSamples)-1,adcReadings[i-1],i+(128-numOfSamples),adcReadings[i]);
  } else {
    for (i=2; i<numOfSamples; i++) // Draw using points
      u8g.drawPixel(i+(128-numOfSamples),adcReadings[i]);
  }
}

void setup() {
  u8g.begin();
  Serial.begin(9600);
 
  // Turn on LED backlight
  analogWrite(lcdLED, ledBacklight);
 
  #if FASTADC
    // set prescale to 16
    sbi(ADCSRA,ADPS2) ;
    cbi(ADCSRA,ADPS1) ;
    cbi(ADCSRA,ADPS0) ;
  #endif
  delay(100);
}

void loop() {
  collectData();
  // Picture Display Loop
  u8g.firstPage(); 
  do { draw(); } while( u8g.nextPage() );

  // If user sends any serial data, show menu
  if (Serial.available() > 0) {
    handleSerial();
  }

  // rebuild the picture after some delay
  delay(100);
}


On importe la bibliothèque "U8glib.h"
On compile et on téléverse.
Et hop: :)



Et pour le branchement des sondes:



Je n'ai rien inventé / codé, j'ai juste adapté ce code trouvé sur le net: http://www.semifluid.com/2013/05/28/arduino-fio-lcd-oscilloscope/

ATTENTION: Ne pas inverser le GND et le + (destruction possible de l'Arduino)
ATTENTION: Ne pas dépasser 5V sur la borne A0 ( le +) (destruction possible de l'Arduino)
voir PONT DIVISEUR DE TENSION pour des tensions supérieurs

Have fun ;)

spyd

  • Global Moderator
  • *****
  • Messages: 1944
    • Voir le profil
  • 3d printer: smartrapcore alu
  • buying date: décembre 2015
  • country/Pays: France
  • region/departement: haute-savoie 74
Re : un oscilloscope "pas chère" ?
« Réponse #1 le: 02 septembre, 2016, 08:43:25 am »
Plus qu'a faire un boitier et travailler le systeme de protection des entrées. ;D
Branchement du ventilo de tête sur le bornier d'alim = HOTEND bien ventillée!!!!!

My thingiverse : http://www.thingiverse.com/spyd6/designs
powerfull tools, free and privacy friendly : https://framasoft.org/[/url