Übung in Echtzeitsysteme: PWM für Servo erzeugen
(EN google-translate)
(PL google-translate)
Ausgehend von einem einfachen Programm und einer einfachen Verstärkerschaltung für den Audioausgang, soll ein Programm entwickelt werden, das es erlaubt direkt zwei Servos über den Auduiausgang angesteuert werden.
Teil 1 - Nachvollziehen eines einfachen Tests, um digitale Pulse an einen Mikrocontroller zu schicken
package processing.test.avrconnect1; import processing.core.*; import android.media.AudioTrack; import android.media.AudioFormat; import android.media.AudioManager; public class avrconnect1 extends PApplet { boolean aktiv = false; int sr; int buffsize; //create an audiotrack object AudioTrack audioTrack; public int PULSE = 15; public int pulse = 0; short[] samples; int amp = 10000; float twopi = 2.0f*PI; float fr = 440.0f; float fr2 = 4.4f; float fr4 = 1.1f; float fr3 = 220.0f; float ph = 0.0f; float ph2 = 0.0f; float ph3 = 0.0f; float ph4 = 0.0f; float change=0.0f; float change2=0.0f; Tonspieler tonspieler; public void setup() { sr = 44100; buffsize = AudioTrack.getMinBufferSize(sr, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); //create an audiotrack object audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sr, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, buffsize, AudioTrack.MODE_STREAM); samples= new short[buffsize]; tonspieler = new Tonspieler(); Thread t = new Thread(tonspieler); t.start(); audioTrack.play(); } public void draw() { clear(); background(0); if(aktiv) fill(0,255,0); else fill(255,0,0); ellipse(width/2,height/2,width/2,height/2); } public void mousePressed() { aktiv = !aktiv; pulse=0; } private class Tonspieler implements Runnable { public void run() { int zaehler = 0; while(true) { if(aktiv) { for(int i=0;i<buffsize;i++) { if(zaehler<2 && pulse<PULSE) { samples[i] = Short.MAX_VALUE; } else samples[i] = Short.MIN_VALUE; // samples[i] = (short)0; zaehler++; if(zaehler>=4) { pulse++; zaehler=0; } } audioTrack.write(samples, 0, buffsize); } } } } }
Code 0-1: Quelltext - Android-seitig
|
Das Programm verschickt bei jedem Einschalten ( mousePressed(), aktiv==true ) 15 Rechteckpulse an den verbundenen Mikrocontroller.
#include<avr/io.h> int main() { unsigned char akku; unsigned char x; unsigned char zahl; DDRB=0; DDRA=0; // PORTA=255; PORTA=0; DDRC=255; akku=0; zahl=0; x=0; PORTC=zahl; while(1) { akku=PINB; x=PINA; if((akku & 0b00000001)>0) zahl=0; if( (x & 0b00000001)>0) { zahl++; while( (x & 0b00000001)>0) { x=PINA; DDRD=0; } } PORTC=zahl; } }
Code 0-2: Mikrocontroller-Quelltext zum Versuch digitale Pulse über den Audio-Ausgang zu übertragen.
Bild 0-1: Versuchsaufbau - digitale Pulse an Mikrocontroller übertragen.
Bild 0-2: Verwendete Verstärkerschaltung.
Musterlösung
Bild 0-3: Verwendete Verstärkerschaltung für Servo-PWM-Signale.
package processing.test.avrconnect1; import processing.core.*; import android.media.AudioTrack; import android.media.AudioFormat; import android.media.AudioManager; public class avrconnect1 extends PApplet { boolean aktiv = false; int sr; int buffsize; long PUFFERZEIT=0; //create an audiotrack object AudioTrack audioTrack; public int PULSE = 400; public int pulse = 0; short[] samples; int amp = 10000; float twopi = 2.0f*PI; float fr = 440.0f; float fr2 = 4.4f; float fr4 = 1.1f; float fr3 = 220.0f; float ph = 0.0f; float ph2 = 0.0f; float ph3 = 0.0f; float ph4 = 0.0f; float change=0.0f; float change2=0.0f; Tonspieler tonspieler; int WERT = 0; public void setup() { sr = 44100; buffsize = AudioTrack.getMinBufferSize(sr, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); PUFFERZEIT = (1000*(long)buffsize)/sr; //create an audiotrack object audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sr, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, buffsize, AudioTrack.MODE_STREAM); samples= new short[buffsize]; tonspieler = new Tonspieler(); Thread t = new Thread(tonspieler); t.start(); audioTrack.play(); } public void draw() { clear(); background(0); if(WERT==0) fill(255,0,0); else if(WERT==1) fill(0,255,0); else fill(0,0,255); ellipse(width/2,height/2,width/2,height/2); } public void mousePressed() { WERT++; WERT%=3; } private class Tonspieler implements Runnable { public void run() { int zaehler = 0; long zeit = System.currentTimeMillis(); while(true) { for(int i=0;i<buffsize;i++) { if(zaehler<44+WERT*22) samples[i] = Short.MAX_VALUE; else samples[i] = Short.MIN_VALUE; zaehler++; if(zaehler>=500) zaehler=0; } audioTrack.write(samples, 0, buffsize); long restzeit = PUFFERZEIT-(System.currentTimeMillis()-zeit); zeit=System.currentTimeMillis(); if(restzeit>0) { try { Thread.sleep(restzeit); } catch(Exception e) { } } } } } }
Code 0-3: Quelltext Musterlösung