Arduino - Multi-Channel oscilloskop (Poor mans oscilloskop) (1 / 1 steg)
Steg 1: Koden
1)
Hämta bearbetning. Behandlingen är en programmeringsmiljö som ser ut och känns identisk med den Arduino programmeringsmiljön. Det kommer också till samma pris, vilket innebär att det är gratis. Klicka här för att ladda ner. Konfigurera den som du ställer in din Arduino programvara. Det går som Arduino IDE.
Bearbetning kan användas för att visa bilder, linjer eller objekt och interagera med dem. Detta är min första erfarenhet av programmet.
2)
Beroende på hur många kanaler vill du ha, ladda upp en "Arduino teckningar" visas nedan i din Arduino. Koden för att skicka och ta emot data bygger på koden i detta stora boken kapitel som förklarar hur att skicka flera textfält från en Arduino till datorn och bearbeta den med bearbetning.
3)
Sedan ta den respektive "Processing skissen" nedan och kopiera den till bearbetning
4)
Ändra "Path" i den sista raden i koden in i en bana som du väljer.
5)
Kör den i bearbetning.
6)
Kontrollera dina signaler inte överstiger 5V innan du ansluter dem till:
Channel1 = > analoga pin0
Channel2 = > analoga pin1
Channel3 = > analoga pin2
Anteckningar:
- Bearbetning skisser använda seriell port 0 eftersom det är standard. Du kan behöva justera det här värdet om du använder en annan serieport.
- Jag dokumenterade varje steg i programmet med massor av kommentarer. Koden bör således vara "självförklarande".
- Jag hittade experimentellt att för vissa konfigurationer data inte kanske visas i realtid på flera sammankopplade orsaker:
- Den fördröjning som är inställd i programmet Arduino är inte tillräckligt stor. = > Too många data skickas. = > Handläggningstiden ackumuleras. = > Data visas med fördröjning. För att testa för förseningar bytt jag manuellt nätaggregatet som var ansluten till min Arduino analoga ingångar av och på utan att frångå spänning svaret visas genom bearbetning. Jag gjorde detta under en längre tid. Om svaret var omedelbar var jag nöjd.
- Om du zoomar i med "+" du visar mindre data. Detta har en direkt effekt på risken för förseningar, eftersom mindre bearbetningstid behövs.
- Fönstret är för bred. = > Too många x-värden måste skiftas. = > Alltför mycket tid som behövs för beräkningar. = > jag valde en mycket mindre fönsterstorlek än min skärmstorlek att ta itu med denna effekt.
Njut av flera kanaler på din fattiga-mans-oscilloskop och låt mig veta om du råkar komma med några förbättringar.
Arduino 2-kanals kod:
/ * CommaDelimitedOutput skiss * /
#define ANALOG_IN_Ch1 0
#define ANALOG_IN_Ch2 1
void setup()
{
Serial.BEGIN(9600);
}
void loop()
{
int värde1 = analogRead(ANALOG_IN_Ch1); / * Läser värden från analoga Pin0 = Channel1 * /
int värde2 = analogRead (ANALOG_IN_Ch2); / * Läser värden från analoga Pin1 = Channel2 * /
Serial.Print('H'); / * Unika huvudet att identifiera början av meddelande * /
Serial.Print(",");
Serial.Print(val1,dec);
Serial.Print(",");
Serial.Print(val2,dec);
Serial.Print(","); / * Observera att skickas ett kommatecken efter det sista fältet * /
Serial.println(); / * Skicka en cr/lf * /
Delay(50); Detta kanske kan vara snabbare än 50 MS
}
Arduino 3-kanals kod:
/ * CommaDelimitedOutput skiss * /
#define ANALOG_IN_Ch1 0
#define ANALOG_IN_Ch2 1
#define ANALOG_IN_Ch3 2
void setup()
{
Serial.BEGIN(9600);
}
void loop()
{
int värde1 = analogRead(ANALOG_IN_Ch1); / * Läser värden från analoga Pin0 = Channel1 * /
int värde2 = analogRead (ANALOG_IN_Ch2); / * Läser värden från analoga Pin1 = Channel2 * /
int val3 = analogRead (ANALOG_IN_Ch3); / * Läser värden från analoga Pin2 = Channel3 * /
Serial.Print('H'); / * Unika huvudet att identifiera början av meddelande * /
Serial.Print(",");
Serial.Print(val1,dec);
Serial.Print(",");
Serial.Print(val2,dec);
Serial.Print(",");
Serial.Print(val3,dec);
Serial.Print(","); / * Observera att skickas ett kommatecken efter det sista fältet * /
Serial.println(); / * Skicka en cr/lf * /
Delay(50);
}
Bearbetning 2-kanals kod:
/*
* Oscilloskop
* Ger en visuell rendering av tre analoga stift i realtid.
*
* Denna programvara expanderar kanal mängden en tidigare version.
Föregående version var ett projekt som är en del av Accrochages
* Se http://accrochages.drone.ws
*
* Författaren av denna anpassad programvara har något samband med Accrochages.
* Han tack dem för stora mallen och inspiration att skriva denna programvara.
*
Följande deklaration var en del av den ursprungliga programvaran.
* Detta är för din information.
*
* (c) 2008 Sofian Gunnels (info
*
* Detta program är fri programvara: du kan vidaredistribuera det och/eller ändra
* det enligt villkoren i GNU General Public License som offentliggjorts av
* Free Software Foundation, antingen version 3 av licensen, eller
* (på ditt alternativ) någon senare version.
*
* Detta program är distribuerat i hopp om att det kommer att vara användbar,
* men utan garantier; utan att ens underförstådd garanti om
* SÄLJBARHET eller lämplighet för ett visst ändamål. Se den
* GNU General Public License för mer detaljer.
*
* Du bör ha fått en kopia av GNU General Public License
* tillsammans med detta program. Om inte, se < http://www.gnu.org/licenses/>.
*/
import processing.serial.*;
Seriella myPort; / * Skapa objekt från seriella klass * /
char huvud = 'H'; / * karaktär att identifiera början av ett meddelande * /
korta LF = 10; / * ASCII radmatning * /
kort portIndex = 0; / * bestämmer USB port används * /
int [] val = {-1, -1}; / * Variabel som används för getY funktion, 2 positioner för 2 kanaler * /
int [] valuesCh1; / * De tre variablerna kommer att hålla data i fönstret i minnet så att de kan skjutas och visas * /
int [] valuesCh2;
float zoom; / * Definiera "zoom" som floating-point variabel * /
void setup()
{
size(1014, 690); / * Öppnar ett fönster av viss storlek, max storlek på min laptop skärm, dröjsmål problem kan uppstå * /
storlek (600, 400); / * mindre skärm = > mindre att beräkna = > utan dröjsmål problem * /
myPort = ny följetong (denna, Serial.list() [portIndex], 9600); / * Öppna porten som styrelsen är ansluten till och använda samma hastighet (9600 bps) * /
valuesCh1 = ny int [bredd]. / * Definiera matris med så många element som x-pixel i fönstret används för att rita data av Channel1 * /
valuesCh2 = ny int [bredd]. / *... av Channel2 * /
Zoom = 1.0f; / * Start med 1 x zoomfaktor * /
Smooth(); / * Rita bilder med jämna kanter * /
}
/ * Den här funktionen omvandlar ett kanal datavärde i pixlar visas från
* toppen av diagrammet (som är 0 position)
* den här funktionen returnerar ett heltalsvärde * /
int getY(int val)
{
tillbaka (int) (höjd - val/1023.0f * (höjd - 1));
}
/ * Funktion som läser in följetong strängdata som skickades av arduino
* Ger ut en matris med tre värdena för arduino
* Funktion kallas i draw funktion * /
int [] getData()
{
int [] ChValues = {-1, -1}; / * Definiera matris för den här funktionen * /
Sträng meddelande = myPort.readStringUntil(LF); / * Läs i seriella strängen skickas av arduino * /
om (meddelande! = null) / * gör detta endast när ett komplett giltig meddelande togs emot * /
{
String [] data = message.split(","); / * Dela kommaavgränsad meddelandet i det segment * /
IF(data[0].charAt(0) == HEADER) / * Check för sidhuvudet karaktär i det första fältet, alltid sant för komplett meddelande * /
{
för (int jag = 1; jag < data.length-1; i ++) / * hoppa över huvudet och avsluta cr och lf = > Titta bara på de tre datapunkterna * /
{
ChValues [i-1] = Integer.parseInt(data[i]); / * Skriva kanaldata till array, jag flyttats från data till array av 1 på grund av huvudet * /
}
}
}
återvända ChValues; / * Avkastning array ChValues som innehåller data för kanaler * /
}
/ * Denna funktion skjuter alla datapunkter i en fönsterposition längst till vänster, sedan lägger den datapunkt som lästes bara * /
void pushValue (int [] värde)
{
för (int jag = 0; jag < bredd-1; i ++)
{
valuesCh1 [i] = valuesCh1 [jag + 1]; / * Flytta data pekar över på på position * /
valuesCh2 [i] = valuesCh2 [jag + 1];
}
valuesCh1 [bredd-1] = värde [0]; / * Lägga till datapunkt * /
valuesCh2 [bredd-1] = värde [1].
}
/ * Funktionen drar data i fönstret * /
void drawLines()
{
int displayWidth (int) = (bredd / zoom); / * Beräknar bredden på fönstret, med tanke på x-change om en zoom är * /
int k = valuesCh1.length - displayWidth; / * Detta beräkna position upp till som datapunkterna visas * /
int x0 = 0; / * x värdet vid mycket till vänster i fönstret (= 0) tilldelas till x0 och används för alla kanaler * /
int ya0 = getY(valuesCh1[k]); / * y värdet av den sista punkten som visas har tilldelats ya0 för channel1 * /
int yb0 = getY(valuesCh2[k]); / * y värdet för den senaste visas punkten tilldelas yb0 för channel2 * /
för (int jag = 1; jag < displayWidth-1; i ++) / * Loop som går från punkt k till mycket höger sida av fönstret * /
{
k ++; / * Öka k för nästa datapunkt * /
int x1 (int) = (jag * (bredd-1) / (displayWidth-1)); / * Beräkna nästa x-värdet * /
int ya1 = getY(valuesCh1[k]); / * Få nästa y-värde för channel1 * /
int yb1 = getY(valuesCh2[k]); / * Få nästa y-värde för channel2 * /
strokeWeight(2); / * Rita tjockare linjer * /
stroke (255, 0, 0); / * Rita en röd linje för channel1 * /
linje (x0, ya0, x1, ya1); / * Rita ett linjesegment för channel1 * /
stroke (0, 255, 0); / * Rita en grön linje för channel2 * /
linje (x0, yb0, x1, yb1); / * Rita ett linjesegment för channel2 * /
x0 = x1; / * Shift x-värdet att beräkna nästa linjesegment * /
ya0 = ya1; / * Shift y-värde för channel1 att beräkna nästa linjesegment * /
yb0 = yb1; / * Shift y-värde för channel2 att beräkna nästa linjesegment * /
}
}
/ * Funktionen drar rutnätslinjer i fönstret
* Jag fördelade rader så att de utgör 10% och 20% stegen i 2 olika färger
* För signaler för 5V max, som är 0,5 & 1.0V steg * /
void drawGrid()
{
stroke (150, 150, 0);
linje (0, höjd/5, bredd, höjd/5);
linje (0, höjd * 2/5, bredd, höjd * 2/5);
linje (0, höjd * 3/5, bredd, höjd * 3/5);
linje (0, höjd * 4/5, bredd, höjd * 4/5);
stroke (150, 150, 150);
linje (0, höjd/10, bredd, höjd/10);
linje (0, höjd * 3/10, bredd, höjd * 3/10);
linje (0, höjd * 5/10, bredd, höjd * 5/10);
linje (0, höjd * 7/10, bredd, höjd * 7/10);
linje (0, höjd * 9/10, bredd, höjd * 9/10);
}
/ * Med denna funktion kan zooma in x-axeln av data
* Körs i bakgrunden och märker när du trycker på höger för
* Zooma in med att trycka på "+"
* Zooma ut med att trycka på "-" * /
void keyReleased()
{
Switch (nyckel)
{
fallet "+":
zoom * = 2.0f;
println(zoom);
om ((int) (bredd / zoom) < = 1)
zoom / = 2.0f;
bryta;
fallet "-":
zoom / = 2.0f;
om (zooma < 1.0f)
zoom * = 2.0f;
bryta;
}
}
/ * Detta är den huvudsakliga funktionen som anropar andra funktioner
* Funktionen körs kontinuerligt * /
void draw()
{
Background(1); / * Ställer in bakgrunden i fönstret * /
drawGrid(); / * Drar rutnätet i fönstret * /
Val = getData(); / * Läser data från tre kanaler som skickas av arduino i en array * /
om (val [0]! = -1) / * om data i första kanalen, sedan utföra funktionen * /
{
pushValue(val); / * Puttar en position data och lägger till en ny datapunkt * /
}
drawLines(); / * Lägga till nästa datamängden i fönstret * /
om (mousePressed) / * utföra åtgärden när musknappen trycks * /
{
Save("/YourPathHere/OsciData1.png"); / * Spara skärmdump av data-fönstret, men se upp bilden kommer att skrivas över med andra musklick * /
}
}
Behandling 3-kanals kod:
/*
* Oscilloskop
* Ger en visuell rendering av tre analoga stift i realtid.
*
* Denna programvara expanderar kanal mängden en tidigare version.
Föregående version var ett projekt som är en del av Accrochages
* Se http://accrochages.drone.ws
*
* Författaren av denna anpassad programvara har något samband med Accrochages.
* Han tack dem för stora mallen och inspiration att skriva denna programvara.
*
Följande deklaration var en del av den ursprungliga programvaran.
* Detta är för din information.
*
* (c) 2008 Sofian Gunnels (info
*
* Detta program är fri programvara: du kan vidaredistribuera det och/eller ändra
* det enligt villkoren i GNU General Public License som offentliggjorts av
* Free Software Foundation, antingen version 3 av licensen, eller
* (på ditt alternativ) någon senare version.
*
* Detta program är distribuerat i hopp om att det kommer att vara användbar,
* men utan garantier; utan att ens underförstådd garanti om
* SÄLJBARHET eller lämplighet för ett visst ändamål. Se den
* GNU General Public License för mer detaljer.
*
* Du bör ha fått en kopia av GNU General Public License
* tillsammans med detta program. Om inte, se < http://www.gnu.org/licenses/>.
*/
import processing.serial.*;
Seriella myPort; / * Skapa objekt från seriella klass * /
char huvud = 'H'; / * karaktär att identifiera början av ett meddelande * /
korta LF = 10; / * ASCII radmatning * /
kort portIndex = 0; / * bestämmer USB port används * /
int [] val = {-1, -1, -1}; / * Variabel som används för getY funktion, 3 lägen för 3channels * /
int [] valuesCh1; / * De tre variablerna kommer att hålla data i fönstret i minnet så att de kan skjutas och visas * /
int [] valuesCh2;
int [] valuesCh3;
float zoom; / * Definiera "zoom" som floating-point variabel * /
void setup()
{
size(1014, 690); / * Öppnar ett fönster av viss storlek, max storlek på min laptop skärm, fördröja problem hälften genom fönstret * /
storlek (600, 400); / * mindre skärm = > mindre att beräkna = > utan dröjsmål problem * /
myPort = ny följetong (denna, Serial.list() [portIndex], 9600); / * Öppna porten som styrelsen är ansluten till och använda samma hastighet (9600 bps) * /
valuesCh1 = ny int [bredd]. / * Definiera matris med så många element som x-pixel i fönstret används för att rita data av Channel1 * /
valuesCh2 = ny int [bredd]. / *... av Channel2 * /
valuesCh3 = ny int [bredd]. / *... av Channel3 * /
Zoom = 1.0f; / * Start med 1 x zoomfaktor * /
Smooth(); / * Rita bilder med jämna kanter * /
}
/ * Den här funktionen omvandlar ett kanal datavärde i pixlar visas från
* toppen av diagrammet (som är 0 position)
* den här funktionen returnerar ett heltalsvärde * /
int getY(int val)
{
tillbaka (int) (höjd - val/1023.0f * (höjd - 1));
}
/ * Funktion som läser in följetong strängdata som skickades av arduino
* Ger ut en matris med tre värdena för arduino
* Funktion kallas i draw funktion * /
int [] getData()
{
int [] ChValues = {-1, -1, -1}; / * Definiera matris för den här funktionen * /
Sträng meddelande = myPort.readStringUntil(LF); / * Läs i seriella strängen skickas av arduino * /
om (meddelande! = null) / * gör detta endast när ett komplett giltig meddelande togs emot * /
{
String [] data = message.split(","); / * Dela kommaavgränsad meddelandet i det segment * /
IF(data[0].charAt(0) == HEADER) / * Check för sidhuvudet karaktär i det första fältet, alltid sant för komplett meddelande * /
{
för (int jag = 1; jag < data.length-1; i ++) / * hoppa över huvudet och avsluta cr och lf = > Titta bara på de tre datapunkterna * /
{
ChValues [i-1] = Integer.parseInt(data[i]); / * Skriva kanaldata till array, jag flyttats från data till array av 1 på grund av huvudet * /
}
}
}
återvända ChValues; / * Avkastning array ChValues som innehåller data för kanaler * /
}
/ * Denna funktion skjuter alla datapunkter i en fönsterposition längst till vänster, sedan lägger den datapunkt som lästes bara * /
void pushValue (int [] värde)
{
för (int jag = 0; jag < bredd-1; i ++)
{
valuesCh1 [i] = valuesCh1 [jag + 1]; / * Flytta data pekar över på på position * /
valuesCh2 [i] = valuesCh2 [jag + 1];
valuesCh3 [i] = valuesCh3 [jag + 1];
}
valuesCh1 [bredd-1] = värde [0]; / * Lägga till datapunkt * /
valuesCh2 [bredd-1] = värde [1].
valuesCh3 [bredd-1] = värde [2].
}
/ * Funktionen drar data i fönstret * /
void drawLines()
{
int displayWidth (int) = (bredd / zoom); / * Beräknar bredden på fönstret, med tanke på x-change om en zoom är * /
int k = valuesCh1.length - displayWidth; / * Detta beräkna position upp till som datapunkterna visas * /
int x0 = 0; / * x värdet vid mycket till vänster i fönstret (= 0) tilldelas till x0 och används för alla kanaler * /
int ya0 = getY(valuesCh1[k]); / * y värdet av den sista punkten som visas har tilldelats ya0 för channel1 * /
int yb0 = getY(valuesCh2[k]); / * y värdet för den senaste visas punkten tilldelas yb0 för channel2 * /
int yc0 = getY(valuesCh3[k]); / * y värdet för den senaste visas punkten tilldelas yc0 för channel3 * /
för (int jag = 1; jag < displayWidth-1; i ++) / * Loop som går från punkt k till mycket höger sida av fönstret * /
{
k ++; / * Öka k för nästa datapunkt * /
int x1 (int) = (jag * (bredd-1) / (displayWidth-1)); / * Beräkna nästa x-värdet * /
int ya1 = getY(valuesCh1[k]); / * Få nästa y-värde för channel1 * /
int yb1 = getY(valuesCh2[k]); / * Få nästa y-värde för channel2 * /
int yc1 = getY(valuesCh3[k]); / * Få nästa y-värde för channel3 * /
strokeWeight(2); / * Rita tjockare linjer * /
stroke (255, 0, 0); / * Rita en röd linje för channel1 * /
linje (x0, ya0, x1, ya1); / * Rita ett linjesegment för channel1 * /
stroke (0, 255, 0); / * Rita en grön linje för channel2 * /
linje (x0, yb0, x1, yb1); / * Rita ett linjesegment för channel2 * /
stroke (0, 0, 255); / * Rita en blå linje för channel3 * /
linje (x0, yc0, x1, yc1); / * Rita ett linjesegment för channel3 * /
x0 = x1; / * Shift x-värdet att beräkna nästa linjesegment * /
ya0 = ya1; / * Shift y-värde för channel1 att beräkna nästa linjesegment * /
yb0 = yb1; / * Shift y-värde för channel2 att beräkna nästa linjesegment * /
yc0 = yc1; / * Shift y-värde för channel3 att beräkna nästa linjesegment * /
}
}
/ * Funktionen drar rutnätslinjer i fönstret
* Jag fördelade rader så att de utgör 10% och 20% stegen i 2 olika färger
* För signaler för 5V max, som är 0,5 & 1.0V steg * /
void drawGrid()
{
stroke (150, 150, 0);
linje (0, höjd/5, bredd, höjd/5);
linje (0, höjd * 2/5, bredd, höjd * 2/5);
linje (0, höjd * 3/5, bredd, höjd * 3/5);
linje (0, höjd * 4/5, bredd, höjd * 4/5);
stroke (150, 150, 150);
linje (0, höjd/10, bredd, höjd/10);
linje (0, höjd * 3/10, bredd, höjd * 3/10);
linje (0, höjd * 5/10, bredd, höjd * 5/10);
linje (0, höjd * 7/10, bredd, höjd * 7/10);
linje (0, höjd * 9/10, bredd, höjd * 9/10);
}
/ * Med denna funktion kan zooma in x-axeln av data
* Körs i bakgrunden och märker när du trycker på höger för
* Zooma in med att trycka på "+"
* Zooma ut med att trycka på "-" * /
void keyReleased()
{
Switch (nyckel)
{
fallet "+":
zoom * = 2.0f;
println(zoom);
om ((int) (bredd / zoom) < = 1)
zoom / = 2.0f;
bryta;
fallet "-":
zoom / = 2.0f;
om (zooma < 1.0f)
zoom * = 2.0f;
bryta;
}
}
/ * Detta är den huvudsakliga funktionen som anropar andra funktioner
* Funktionen körs kontinuerligt * /
void draw()
{
Background(1); / * Ställer in bakgrunden i fönstret * /
drawGrid(); / * Drar rutnätet i fönstret * /
Val = getData(); / * Läser data från tre kanaler som skickas av arduino i en array * /
om (val [0]! = -1) / * om data i första kanalen, sedan utföra funktionen * /
{
pushValue(val); / * Puttar en position data och lägger till en ny datapunkt * /
}
drawLines(); / * Lägga till nästa datamängden i fönstret * /
om (mousePressed) / * utföra åtgärden när musknappen trycks * /
{
Save("/YourPathHere/OsciData1.png"); / * Spara skärmdump av data-fönstret, men se upp bilden kommer att skrivas över med andra musklick * /
}
}