Mätapplikation med Arduino och Java

Berätta om dina pågående projekt.
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Kom igång med projektet efter en tids uppehåll med blåskärm i windows 10.
Och efter att ha laddat hem Eclipse, WindowsBuilder och Arduino-pluginnet på nytt och förmodligen gjort allt mer rätt
den här gången så fungerar allt så mycket smidigare.

På något sätt tror jag Arduino ide lagt till något för info om USB-porten då den alltid dök upp med namnet Arduino inbakat.
Nu verkar den alltid koppla upp sig med COM3 men eftersom jag inte vet om det alltid är så så valde jag att ha en lista
med de portar som finns och sedan får man klicka på den port man misstänker hör till Arduino.

Man kanske skulle kunna ha kod på Arduinon och pinga men då måste man ju göra det på alla portar och dessutom öppna dom
och sätta upp scannern och DataOutputStream först.

På något sätt måste jag i alla fall ta reda på om det är Arduino som finns på den porten annars
kan det hända att allt ser bra ut och den verkar uppkopplad men när man väl kör igång med
kommunikationen så dyker programmet.

Så här ser guit ut nu i vilket fall och klickar jag på rätt port så fungerar det bra.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Hittade en variant som går ut på att antalet tillgängliga portar scannas av och så
kopplar man bort resp. ansluter USB-kontakten och när kodsnutten känner av
förändringen i antal portar så presenteras den nyupptäckta porten som Arduino.

Labbade med com-portsinställningar i enhetshanteraren och upptäckte att det inte
fungerar att ändra comports-nummer medans Arduino är ansluten och tro att det ska
gå att koppla upp sig sedan. Det fungerar om man drar ur USB-kontakten och sedan
ansluter igen. Vet inte om det kanske har att göra med com.fazecast.jSerialComm?
Zhorts
Inlägg: 217
Blev medlem: 15 augusti 2011, 14:42:03

Re: Mätapplikation med Arduino och Java

Inlägg av Zhorts »

Att byta nummer på COM-porten under löpande körning är troligen ett Windows-problem... Windows är inte överdrivet bra på att hantera CAN-portar, och mellansteget med USB gör inte saken bättre.
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Tror mig hittat en lösning för att hitta rätt com-port att koppla upp programmet emot.

Det hela går ut på att skanna av vilka portar som är anslutna och sedan koppla ifrån, eller dra ut, Arduino-kontakten.
När skillnaden i antal portar analyserats så jämför jag 2 stackar och den port som inte fanns med är uppenbarligen
den som plockades bort, alltså den till Arduino.

Den porten presenteras i en klickbar label som COM3 i exemplet nedan. Klickar man nu på den labeln så
öppnas kommunikationen och in och utdataström konfigureras.

Programmet är startat...
java_GUI_100.png
START för uppkoppling är aktiverad...
java_GUI_101.png
USB-kontakten är bortkopplad och tillbakasatt...
java_GUI_102.png
Labeln med COM 3 är klickad på...
java_GUI_103.png
Här är den kod som kör som en tråd så länge programmet är igång.
Det finns en del kontroll i händelsehanterarna till START och den klickbara labeln
så inte tråden startas på nytt utan att det behövs plus för att undvika några andra problem
för handhavandefel.

Kod: Markera allt

import com.fazecast.jSerialComm.SerialPort;

/*****************************************************************************************************
 * 	Ett objekt av denna klass körs som en tråd tills hela programmet avslutas.
 *  Klassen sköter om uppkoppling och nedkoppling av seriekommunikationen med Arduino.
 * 	Genom att utföra avbrott i tråden som kör trådkontrollern så kopplas porten ned
 *  Detta utför till exempel då knappen EXIT aktiveras.
 *  Skapar ett scannerobjekt för att läsa data från Arduino
 *  Skapar en DataOutputStream för att skriva till Arduino  
 *  
 *  Metoder som ingår i klassen:
 *  
 *  public static void comPortConnect()
 *  public void comPortSetUp()
 *  public static boolean getComPortSetUpFlag()
 *  private void fillStackA()
 *  private void fillStackB()
 *  private void comPortCloseDown()
 *	public static int getBaudRate()
 *	public static SerialPort getSerialPort()
 *	public String toString() 
 *****************************************************************************************************/

public class Test implements Runnable {
	private static SerialPort serialPort; 						// instans skapas i metoden comPortSetUp()
	private static int baudRate;								// serieportens i GUI valda överföringshastighet
	private static SerialPort[] sp;	
	private static StringStack stackA;
	private static StringStack stackB;
	private static String id;
	private static boolean found;
	private static boolean comPortSetUpFlag;
	public Test(int baudrate) {
		baudRate = baudrate;
		stackA = new StringStack();
		stackB = new StringStack();
		id = "";
		found = true;
	}
	/*
	 * En tråd av denna klass kopplar upp Arduino via den serieport där den finns ansluten.
	 * När tråden avbryts, sker vid EXIT i GUI, så kopplas porten ned.
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		comPortSetUp();		
		while(true) {
			if(Thread.interrupted()) {																															
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}				
				comPortCloseDown();	
				System.out.println("Tråden " + toString() + " är avslutad");
				break;							
			}
		}
	}
	/*
	 * En lista med com-portar finns att välja bland där en av dessa är den identifierade i 
	 * Arduino-porten. Metoden comPortSetUp() i denna klass identifierar porten.
	 * När identifieringen gjorts utförs ett försök att öppna den via ett musklick i GUI som
	 * startar denna metod. Metoden låser den klickbara labeln med portnamnet så metoden inte
	 * körs mer än en gång. Endast om USB-kontakten inte var ansluten låses labeln upp och
	 * man får starta med comPortSetUp() på nytt.
	 * Vidare konfigureras portens baudrate och timeouts samt att Scannern och DataOutPutStream
	 * aktiveras. En mjukvarureset av Arduino utförs genom att lägga DTR-linan låg en kort stund.
	 */
	public static void comPortConnect() {
		NTC.setLabelConnectArduinoPortActiveFlag(false);	// förhindra att Com-ports-label är klickbar
		sp = SerialPort.getCommPorts();
		for(int k=0;k<sp.length;k++) {						// leta reda på Arduino-porten
			if(sp[k].getSystemPortName().equals(id)) {
				serialPort = sp[k];
				break;
			}
		}
		if(serialPort != null) {
			serialPort.openPort();
			serialPort.setBaudRate(baudRate);
			serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 2500, 0);
			// värdet 2500 [ms] måste ökas om processen som Arduino mäter på är långsam.
			NTC.newArduinoScanIn();
			NTC.newjavaToArduinoOut();
			if(!serialPort.isOpen()) {
				serialPort.openPort(); 						// Open connection
				System.out.println("port is open = "+ serialPort.isOpen());
			}
			if(serialPort.isOpen()) {
				NTC.setArduinoConnectedFlag(serialPort.isOpen());
				System.out.println("port is open = "+ serialPort.isOpen());
			}					
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			serialPort.clearDTR();									// Arduino Reset
			System.out.println("Arduino är Uppkopplad");
			System.out.println("Scanner och DataOutputStream är konfigurerade");
			NTC.getDisplay().asyncExec (new Runnable () {			
				public void run () { 								// Informativ text i GUI om com-portens baudrate
					NTC.changeComPortLabel("Arduino är uppkopplad med " + Test.getBaudRate() + " bts");
					NTC.setArduinoConnectedFlag(true);
				}
			});
		}
		else {														// om usb-kontakten inte var ansluten
			NTC.getDisplay().syncExec (new Runnable () {				
				public void run () {
					NTC.changeComPortLabel("Anslut USB-kontakten\noch tryck START på nytt");
					NTC.getLabelConnectArduinoPort().setText("COM PORT");
				}
			});
		}			
	} 
	/*
	 *  Skannar av vilka com-portar som finns tillgängliga och i GUI presenteras en av dessa
	 *  som den aktuella Arduino-porten. Arduino-porten identifieras genom att ta ur och sätta
	 *  i den fysiska USB-kontakten.
	 */
	public static void comPortSetUp() {
		comPortSetUpFlag = true;
		found = true;
		stackA.clearStack();
		stackB.clearStack();
		NTC.getDisplay().syncExec (new Runnable () {				
			public void run () {
				NTC.changeComPortLabel("Dra ur och Sätt i USB-kontakten\nVälj sedan port från fältet nedan");				
			}
		});
		fillStackA();									// fyll stackA med anslutna portar
		while(found) {									// invänta att Arduino kopplas bort eller läggs till
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			} 
			fillStackB();									// fyll stackB med anslutna portar
			if(stackA.stackSize() > stackB.stackSize()) {	// om antal skiljer sig så jämför innehållet i stackA och stackB
				while(found) {
					id = stackA.pop();
					found = stackB.searchForString(id);
					if(!found) {
						System.out.println("id = " + id);
						NTC.getDisplay().syncExec (new Runnable () {	// presentera Arduino-porten			
							public void run () {
								NTC.getLabelConnectArduinoPort().setText(id);
							}
						});
						NTC.setLabelConnectArduinoPortActiveFlag(true);	// tillåt att presentations-label med Arduino-porten är klickbar
					}
				}
			}
			if(stackB.stackSize() > stackA.stackSize()) {		// om antal skiljer sig så jämför innehållet i stackA och stackB
				while(found) {
					id = stackB.pop();
					found = stackA.searchForString(id);
					if(!found) {
						System.out.println("id = " + id);
						NTC.getDisplay().syncExec (new Runnable () {	// presentera Arduino-porten				
							public void run () {
								NTC.getLabelConnectArduinoPort().setText(id);
							}
						});
						NTC.setLabelConnectArduinoPortActiveFlag(true);	// tillåt att presentations-label med Arduino-porten är klickbar
					}
				}
			}
		}
		System.out.println("Exit Comportsetup");
		comPortSetUpFlag = false;
	}
	/*
	 * En flagga som visar om metoden comPortSetUp() exekveras.
	 * Den används av START-knappen till denna trådkörning så man inte försöker
	 * skapa och starta en ny tråd mitt under pågående set up.
	 */
	public static boolean getComPortSetUpFlag() {
		return comPortSetUpFlag;
	}
	/*
	 * Lägg upp alla anslutna com-portar på stackA
	 */
	private static void fillStackA() {
		stackA.clearStack();
		sp = SerialPort.getCommPorts();
		for(int j=0;j<sp.length;j++) {							
			NTC.setComPortId(j);
			NTC.getDisplay().syncExec (new Runnable () {				
				public void run () {							
					stackA.push(sp[NTC.getComPortId()].getSystemPortName());														
				}
			});																
		}
	}
	/*
	 * Lägg upp alla anslutna com-portar på stackB	
	 */
	private static void fillStackB() {								
		stackB.clearStack();
		sp = SerialPort.getCommPorts();
		for(int j=0;j<sp.length;j++) {								
			NTC.setComPortId(j);
			NTC.getDisplay().syncExec (new Runnable () {				
				public void run () {							
					stackB.push(sp[NTC.getComPortId()].getSystemPortName());														
				}
			});																
		}
	}

	/*
	 * Stänger porten. Sker först när knappen EXIT i GUI aktiveras som då
	 * avbryter run-metoden i denna klass
	 */
	private void comPortCloseDown() {
		if(serialPort != null)
			serialPort.closePort();
		NTC.setArduinoConnectedFlag(false);							
	}

	/*
	 * Returnerar aktuellt satt baudrate
	 */
	public static int getBaudRate() {
		return baudRate;
	}	
	public static SerialPort getSerialPort() {
		return serialPort;
	}
	public String toString() {
		return "ComPortConnect";
	}
}

Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Hur fungerar det med t.ex. en USB-mus ansluten,
com.fazecast.jSerialComm.SerialPort listar inte att
den används?
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Försöker få bättre precision i bryggan som ska mäta NTC-motståndet.
Som det ser ut nu diffar det aningen för mycket från en rät linje.

Så jag testade att nolla bryggan med ett 680ohms motstånd och sedan anslöt jag ett antal
uppmätta motstånd ända ned till ett 47 ohms.
I plotten syns den svarta linjen med punkter motsvarande de värden jag anslutit.
Jag kan alltså inte interpolera med en rät linje så därför är jag inne på att använda ett
polynom då det finns bra stöd för detta från Apache mattebibliotek som jag också
laddade hem.

I första exemplet tas konstanterna till f(x) = a + bx fram, alltså en rät linje.
I andra exemplet en kurva på formen f(x) = a + bx + cx^2 som blir i princip den samma
som kurvan v(x) = -0.0458x^0.6188 + 2.582 vilket är den matteprogrammet kom fram till (pwrfit).
Jag kollade lite på hur den kurvan tas fram men det blir en del matte som man måste plöja igenom
så det blir bra mycket enklare att använda Apache-biblioteket org.apache.commons.math3.fitting.PolynomialCurveFitter

Jag ska också ta och testa med att se hur bra det kan bli med enbart 3 olika motståndsvärden, 47, 390 och 680 som exempel.
Det underlättar att bara behöva trimma in kurvan med 3 motstånd och jag har inte extrema krav på att kurvan ger rätt
motståndsvärde men lite bättre än en diff på 50 ohm vore kul att få till.

Kod: Markera allt

import java.text.DecimalFormat;
import java.util.Locale;
import org.apache.commons.math3.fitting.PolynomialCurveFitter;
import org.apache.commons.math3.fitting.WeightedObservedPoints;

/*
 * f(x) = a + bx + cx^2
 */
public class Exempel {
	private static Exempel exempel;
	private PolynomialCurveFitter pcf;
	private double[] coeff;	
	private WeightedObservedPoints obs = new WeightedObservedPoints();
	private Locale s = Locale.getDefault();
	DecimalFormat myFormatter = new DecimalFormat("##0.##E0");
	
	public static void main(String[] args) {		
		Locale.setDefault(Locale.ENGLISH);
		exempel = new Exempel();
		exempel.data();
		exempel.show();
	}
	public void data() {
		obs.add(680, 0);
		obs.add(467, 0.513);
		obs.add(391, 0.762);
		obs.add(47.3, 2.087);		
	}

	public void show() {
		pcf = PolynomialCurveFitter.create(2);
		coeff = pcf.fit(obs.toList());
		for(int i=0;i<coeff.length;i++) {
			if(i == 0)
				System.out.printf(s,"a = " + myFormatter.format(coeff[i])+"\n");	
			if(i == 1)
				System.out.printf(s,"b = " + myFormatter.format(coeff[i])+"\n");	
			if(i == 2) 
			     System.out.printf(s,"c = " + myFormatter.format(coeff[i])+"\n");				
		}
	}
}
Output:

Kod: Markera allt

a = 2.3084E0
b = -4.7609E-3
c = 2.0056E-6
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Här har jag lagt in 7 punkter och använt 3 av dessa värden för att generera polynomet.

Kod: Markera allt

	public void data() {
		obs.add(680, 0);
		obs.add(391, 0.762);
		obs.add(47.3, 2.087);		
	}
Resultat:

Kod: Markera allt

a = 2.305E0
b = -4.6992E-3
c = 1.9258E-6
Som synes diffar det som mest från 450 - 560 ohm men inte så mycket, acceptabelt tycker jag.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Zhorts
Inlägg: 217
Blev medlem: 15 augusti 2011, 14:42:03

Re: Mätapplikation med Arduino och Java

Inlägg av Zhorts »

Ett tips: För att snabbt och enkelt utvärdera hur bra en kurva passar en annan: Ta den ena minus den andra, och plotta felet. Procentuellt eller absolut, beroende på vilken sida man vaknade på.

Ett andragradspolynom ser ju ut att duga fint - beroende på exakt vad du ska mäta, naturligtvis...
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Jag funderar på om det är något som skulle kunna förbättras i kretsen jag använder?
Kanske matcha motstånden i förstärkarna eller använda andra förstärkare?
Jag använder inte AD822 som i schemat men i övrigt stämmer värdena.
1V genererar jag från en spänningsdelare med en 7805 som regulator och den
håller spänningen bra. Om det är 1V eller 1.01V spelar ingen roll för hur olinjärt det blir.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Så här kan det se ut efter att ha mätt upp bryggan med 3 motstånd, 680, 390 och 47 ohm.

Använder mig av klassen Polynomial för ändamålet.

Ska snart börja labba med styrning av värmeelement.
Jag adderade en funktion för att kontinuerligt mäta spänningen från bryggan,
en voltmeter helt enkelt.

Kod: Markera allt

import org.apache.commons.math3.fitting.PolynomialCurveFitter;
import org.apache.commons.math3.fitting.WeightedObservedPoints;
/*
 * Klassen används för att ta fram ett andragradspolynom
 * på formen A + Bx + Cx^2
 * 
 */
public class Polynomial {
	private double A;
	private double B;
	private double C;
	private PolynomialCurveFitter pcf;
	private double[] constants;	
	private WeightedObservedPoints obs;
	
	public Polynomial() {
		A = B = C = 0;
		pcf = PolynomialCurveFitter.create(2);
		obs = new WeightedObservedPoints();
	}

	public void calcPolynomialConstants() {
		constants = pcf.fit(obs.toList());
		for(int i=0;i<constants.length;i++) {
			if(i==0) {
				A = constants[i];
				System.out.println(constants[i]);
			}				
			if(i==1) {
				B = constants[i];
				System.out.println(constants[i]);
			}				
			if(i==2) {
				C = constants[i];
				System.out.println(constants[i]);
			}					
		}		
	}
	public void addPoint(double ohm, double volt) {
		obs.add(ohm, volt);
	}
	public void clearDataPoints() {
		obs.clear();
		A=B=C=0;
	}
	public double getConstA() {
		return A;
	}
	public double getConstB() {		
		return B;
	}
	public double getConstC() {
		return C;
	}
}

Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Håller på att labba med ritfunktioner i Java därför att jag eventuellt ville ha med
grafen på den interpolerade kurvan och samtidigt plotta de uppmätta värdena i
realtid. Jag tänker mig en Canvas som kurvan ritas i med automatiskt satta markers
på x- och y-axel. Det är lite att lära in och en del läsning för att få det som jag vill.
Jag har inte ritat kurvan ännu men väl markers och axlar.
Jag använder i nuläget 3 klasser. Java kräver inte så hemskt mycket kod för det här.

Kod: Markera allt

import javax.swing.JFrame;
import java.awt.SystemColor;
import javax.swing.JButton;
import javax.swing.Box;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JSpinner;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import java.awt.Font;
import java.awt.Label;
import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

public class SwingWindow extends JFrame {

	private static final long serialVersionUID = 1L;
	public final int WINDOW_WIDTH = 515;
	public final int WINDOW_HEIGHT = 400;
	public final int SPINNER_X_STARTVALUE = 0;
	public final int SPINNER_Y_STARTVALUE = 0;
	private static JButton b0;
	private static JButton b1;
	private static JButton b2;
	private static JSpinner spinner_X;
	private static JSpinner spinner_Y;
	private static int spinner_X_value;
	private static int spinner_Y_value;
	private static Label label_Y;
	private static Label label_X;
	private JSpinner spinner_dX;
	private JSpinner spinner_dY;
	private static SwingWindow window;
	private static MyCanvas canvas;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					window = new SwingWindow();
					window.setVisible(true);
					canvas.setFocusable(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public SwingWindow() {
		super("Swing");		
		getContentPane().setBackground(SystemColor.window);
		getContentPane().setLayout(null);
		setForeground(SystemColor.textText);
		setBackground(SystemColor.window);
		setBounds(400, 100, WINDOW_WIDTH, WINDOW_HEIGHT);
		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);	
		setUpGUI();
	}
	
	/**
	 * Initialize the contents of the frame.
	 */
	private void setUpGUI() {
		canvas = new MyCanvas();
		canvas.addFocusListener(new FocusListener() {
			@Override
			public void focusGained(FocusEvent e) {
				System.out.println("focus");			
			}
			@Override
			public void focusLost(FocusEvent e) {
				System.out.println("ur focus");	
			}	
		});
		getContentPane().add(canvas);
		JPanel panel = new JPanel();
		panel.setBackground(SystemColor.menu);
		panel.setBounds(10, 275, 474, 76);
		getContentPane().add(panel);
		panel.setLayout(null);
		
		Box horizontalBox_1 = Box.createHorizontalBox();
		horizontalBox_1.setBounds(20, 11, 438, 20);
		panel.add(horizontalBox_1);
		
		JLabel label_Ymax = new JLabel("Ymax");
		horizontalBox_1.add(label_Ymax);
		
		Component rigidArea = Box.createRigidArea(new Dimension(20, 20));
		horizontalBox_1.add(rigidArea);
		
		spinner_Y = new JSpinner();
		spinner_Y.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				spinner_Y_value = (int) spinner_Y.getValue();
				label_Y.setText(String.valueOf(spinner_Y_value));
				canvas.setNewY(spinner_Y_value);
			}
		});
		horizontalBox_1.add(spinner_Y);
		
		Component rigidArea_5 = Box.createRigidArea(new Dimension(20, 20));
		horizontalBox_1.add(rigidArea_5);
		
		JLabel label_Xmax = new JLabel("Xmax");
		horizontalBox_1.add(label_Xmax);
		
		Component rigidArea_1 = Box.createRigidArea(new Dimension(20, 20));
		horizontalBox_1.add(rigidArea_1);
		
		spinner_X = new JSpinner();
		spinner_X.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				spinner_X_value = (int) spinner_X.getValue();
				label_X.setText(String.valueOf(spinner_X_value));
				canvas.setNewX(spinner_X_value);
			}
		});
		horizontalBox_1.add(spinner_X);
		
		Component rigidArea_8 = Box.createRigidArea(new Dimension(20, 20));
		horizontalBox_1.add(rigidArea_8);
		
		JLabel label_dY = new JLabel("dY");
		horizontalBox_1.add(label_dY);
		
		Component rigidArea_6 = Box.createRigidArea(new Dimension(20, 20));
		horizontalBox_1.add(rigidArea_6);
		
		spinner_dY = new JSpinner();
		horizontalBox_1.add(spinner_dY);
		
		Component rigidArea_7 = Box.createRigidArea(new Dimension(20, 20));
		horizontalBox_1.add(rigidArea_7);
		
		JLabel label_dX = new JLabel("dX");
		horizontalBox_1.add(label_dX);
		
		Component rigidArea_9 = Box.createRigidArea(new Dimension(20, 20));
		horizontalBox_1.add(rigidArea_9);
		
		spinner_dX = new JSpinner();
		horizontalBox_1.add(spinner_dX);
		Box horizontalBox = Box.createHorizontalBox();
		horizontalBox.setBounds(20, 42, 438, 23);
		panel.add(horizontalBox);
		
		b0 = new JButton("Ny Skala");
		b0.setMaximumSize(new Dimension(120, 23));
		horizontalBox.add(b0);
		
		Component rigidArea_2 = Box.createRigidArea(new Dimension(20, 20));
		horizontalBox.add(rigidArea_2);
		
		b1 = new JButton("B");
		b1.setMaximumSize(new Dimension(120, 23));
		horizontalBox.add(b1);
		
		Component rigidArea_3 = Box.createRigidArea(new Dimension(20, 20));
		horizontalBox.add(rigidArea_3);
		
		b2 = new JButton("C");
		b2.setMaximumSize(new Dimension(120, 23));
		horizontalBox.add(b2);
		
		JButton b3 = new JButton("Avsluta");
		b3.setMaximumSize(new Dimension(120, 23));
		b3.addActionListener(new Listener().new Avbryt());
		
		Component rigidArea_4 = Box.createRigidArea(new Dimension(20, 20));
		horizontalBox.add(rigidArea_4);
		horizontalBox.add(b3);
		
		JPanel panel_1 = new JPanel();
		panel_1.setBackground(SystemColor.text);
		panel_1.setBounds(10, 252, 474, 20);
		getContentPane().add(panel_1);
		panel_1.setLayout(null);
		
		label_Y = new Label(String.valueOf(SPINNER_Y_STARTVALUE));
		label_Y.setFont(new Font("Arial Black", Font.BOLD, 15));
		label_Y.setAlignment(Label.CENTER);
		label_Y.setForeground(Color.BLACK);
		label_Y.setBackground(Color.YELLOW);
		label_Y.setBounds(10, 0, 106, 20);
		panel_1.add(label_Y);
		
		label_X = new Label(String.valueOf(SPINNER_X_STARTVALUE));
		label_X.setForeground(Color.BLACK);
		label_X.setFont(new Font("Arial Black", Font.BOLD, 15));
		label_X.setBackground(Color.YELLOW);
		label_X.setAlignment(Label.CENTER);
		label_X.setBounds(122, 0, 106, 20);
		panel_1.add(label_X);
	}
}

Kod: Markera allt

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.SystemColor;

public class MyCanvas extends Canvas{
	private static final long serialVersionUID = 1L;
	public final int CANVAS_WIDTH = 480;
	public final int CANVAS_HEIGHT = 240;
	public final int AXIS_MARGIN = 40;
	public final int SCALEX = 7;
	public final int SCALEY = 10;
	private int xAxisLength;
	private int yAxisLength;
	private int x1Axis;
	private int y1Axis;
	private int y2Axis;
	private int xAxisStartPoint;
	private int xAxisEndPoint;
	private int yAxisStartPoint;
	private int yAxisEndPoint;
	
	private int x1;
	private int y1;
	private int x2;
	private int y2;
	private Graphics2D g2;
	
	public MyCanvas() {
		x1 = 0;
		y1 = 0;
		x2 = 0;
		y2 = 0;
		setBackground(SystemColor.info);
		setBounds(10, 10, CANVAS_WIDTH, CANVAS_HEIGHT);
	}

	public MyCanvas(GraphicsConfiguration config) {
		super(config);
		// TODO Auto-generated constructor stub
	}

	public void paint(Graphics g) {				
		g2 = (Graphics2D) g;
		g2.drawLine(x1, y1, x2, y2);
		drawAxis();
		drawMarkers();
	}
	public void drawXMarker(int xpos) {
		super.getGraphics().drawLine(xpos, y2Axis-3, xpos, y2Axis+3);		
	}
	public void drawYMarker(int ypos) {
		super.getGraphics().drawLine(x1Axis-3, ypos, x1Axis+3, ypos);		
	}
	public void drawAxis() {
		
		xAxisLength = CANVAS_WIDTH - AXIS_MARGIN;				
		yAxisLength = CANVAS_HEIGHT - AXIS_MARGIN;				
		x1Axis = CANVAS_WIDTH - xAxisLength - AXIS_MARGIN/2; 	
		y1Axis = CANVAS_HEIGHT - yAxisLength - AXIS_MARGIN/2;											
		y2Axis = CANVAS_HEIGHT - AXIS_MARGIN/2;
		xAxisStartPoint = x1Axis;
		xAxisEndPoint = xAxisLength + x1Axis;
		yAxisStartPoint = y2Axis;
		yAxisEndPoint = y1Axis;
		super.getGraphics().drawLine(xAxisStartPoint, yAxisEndPoint, xAxisStartPoint, yAxisStartPoint);	//y-axel
		super.getGraphics().drawLine(x1Axis, y2Axis, xAxisEndPoint, y2Axis);							//x-axel
		
	}
	public int getXaxisLength() {
		return xAxisLength;
	}
	public int getYaxisLength() {
		return yAxisLength;
	}
	public int getXaxisStartPoint() {
		return xAxisStartPoint;
	}
	public int getYaxisStartPoint() {
		return yAxisStartPoint;
	}
	public int getXaxisEndPoint() {
		return xAxisEndPoint;
	}
	public int getYaxisEndPoint() {
		return yAxisEndPoint;
	}
	public void setX1(int x) {
		x1 = x;		
	}
	public void setY1(int y) {
		y1 = y;
	}
	public void setNewX(int x) {
		x1 = x2;
		x2 = x;
		super.getGraphics().drawLine(x1, y1, x2, y2);
	}
	public void setNewY(int y) {
		y1 = y2;
		y2 = y;
		super.getGraphics().drawLine(x1, y1, x2, y2);
	}
	private void drawMarkers() {
		int dx = getXaxisLength()/SCALEX;
		int dy = getYaxisLength()/SCALEY;
		int xs = getXaxisStartPoint();
		int xe = getXaxisEndPoint();
		int ys = getYaxisStartPoint();
		int ye = getYaxisEndPoint();
		System.out.println(String.valueOf(ys));
		System.out.println(String.valueOf(ye));
		System.out.println(String.valueOf(dy));
		for(int i=xs;i<=xe;i+=dx) {
			drawXMarker(i);
		}								
		for(int i=ye;i<=ys;i+=dy) {
			drawYMarker(i);
		}
	}
}

Kod: Markera allt

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;

public class Listener extends JFrame{
	private static final long serialVersionUID = 1L;
	public Listener() {
		
	}

	public class Avbryt implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			System.exit(0);			
		}		
	}
}
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Då det vore kul med en kurva på det som mäts plus den kurva som
polynomapproximerats och kunna skriva ut denna från NTC-programmet
så har jag dykt ned i kodningen av grafik i Java.

Jag har labbat med att rita axlar i en lagerbild och sedan
plotta kurvan i en annan lagerbild då jag upptäckte att om
jag ville ha en marker för x och y så måste kurvan plottas på
nytt vilket inte blir bra. Att byta en bild går betydligt snabbare
men jag har inte helt testat detta ännu.

I vilket fall så har jag lyckats rita två lager uppepå varandra
med en viss genomskinlighet och det anser jag vara en bra start.
Main...

Kod: Markera allt

import javax.swing.JFrame;
import java.awt.SystemColor;
import javax.swing.JButton;
import javax.swing.Box;
import java.awt.Component;
import java.awt.Dimension;
//import java.awt.EventQueue;
import javax.swing.JSpinner;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import java.awt.Font;
import java.awt.Label;
import java.awt.Color;
import javax.swing.SpringLayout;
import javax.swing.SpinnerNumberModel;

public class SwingWindow extends JFrame {
	
	private static final long serialVersionUID = 1L;
	public final int WINDOW_WIDTH = 800;
	public final int WINDOW_HEIGHT = 500;
	public static final int CANVAS_WIDTH = 772;
	public static final int CANVAS_HEIGHT = 365;
	public final int SPINNER_X_STARTVALUE = 0;
	public final int SPINNER_Y_STARTVALUE = 0;
	// y = 2.31 - 0.0047*x + 1.93*10^-6*x^2
	public static final double A = 2.31;
	public static final double B = -0.0047;
	public static final double C = 0.00000193;
	private static JButton b0;
	private static JButton b1;
	private static JButton b2;
	private static JSpinner spinner_X;
	private static JSpinner spinner_Y;
	private static int spinner_X_value;
	private static int spinner_Y_value;
	private static Label label_Y;
	private static Label label_X;
	private JSpinner spinner_dX;
	private JSpinner spinner_dY;
	public static SwingWindow swingwindow;
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		swingwindow = new SwingWindow();
		swingwindow.setVisible(true);
		/*EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					new SwingWindow();
					
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}); */
	}

	/**
	 * Create the application.
	 */
	public SwingWindow() {
		super("Swing");	
		setMaximumSize(new Dimension(1000, 800));
		getContentPane().setBackground(new Color(240, 230, 140));
		getContentPane().setLayout(null);
		setBounds(400, 100, WINDOW_WIDTH, WINDOW_HEIGHT);
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);	
		setUpGUI();
	}
	/**
	 * Initialize the contents of the frame.
	 */
	private void setUpGUI() {		
		JPanel panel = new JPanel();
		panel.setBackground(SystemColor.menu);
		panel.setBounds(5, 376, 575, 76);
		getContentPane().add(panel);
		SpringLayout sl_panel = new SpringLayout();
		panel.setLayout(sl_panel);
		
		Box horizontalBox_1 = Box.createHorizontalBox();
		sl_panel.putConstraint(SpringLayout.WEST, horizontalBox_1, 10, SpringLayout.WEST, panel);
		sl_panel.putConstraint(SpringLayout.EAST, horizontalBox_1, -10, SpringLayout.EAST, panel);
		horizontalBox_1.setOpaque(true);
		sl_panel.putConstraint(SpringLayout.NORTH, horizontalBox_1, 11, SpringLayout.NORTH, panel);
		panel.add(horizontalBox_1);
		
		JLabel lblYMarker = new JLabel("Y1 marker");
		horizontalBox_1.add(lblYMarker);
		
		Component rigidArea = Box.createRigidArea(new Dimension(20, 20));
		rigidArea.setMinimumSize(new Dimension(15, 20));
		rigidArea.setPreferredSize(new Dimension(15, 20));
		rigidArea.setMaximumSize(new Dimension(15, 20));
		horizontalBox_1.add(rigidArea);
		
		spinner_Y = new JSpinner();
		spinner_Y.setDoubleBuffered(true);
		spinner_Y.setMinimumSize(new Dimension(50, 20));
		spinner_Y.setPreferredSize(new Dimension(50, 20));
		spinner_Y.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				spinner_Y_value = (int) spinner_Y.getValue();
				label_Y.setText(String.valueOf(spinner_Y_value));
				//canvas.setNewY(spinner_Y_value);
			}
		}); 
		horizontalBox_1.add(spinner_Y);
		
		Component rigidArea_5 = Box.createRigidArea(new Dimension(20, 20));
		rigidArea_5.setMinimumSize(new Dimension(15, 20));
		rigidArea_5.setPreferredSize(new Dimension(15, 20));
		rigidArea_5.setMaximumSize(new Dimension(15, 20));
		horizontalBox_1.add(rigidArea_5);
		
		JLabel lblXMarker = new JLabel("X1 marker");
		horizontalBox_1.add(lblXMarker);
		
		Component rigidArea_1 = Box.createRigidArea(new Dimension(20, 20));
		rigidArea_1.setMinimumSize(new Dimension(15, 20));
		rigidArea_1.setPreferredSize(new Dimension(15, 20));
		rigidArea_1.setMaximumSize(new Dimension(15, 20));
		horizontalBox_1.add(rigidArea_1);
		
		spinner_X = new JSpinner();
		spinner_X.setModel(new SpinnerNumberModel(0, 0, 700, 1));
		spinner_X.setDoubleBuffered(true);
		spinner_X.setMinimumSize(new Dimension(50, 20));
		spinner_X.setPreferredSize(new Dimension(50, 20));
		spinner_X.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				spinner_X_value = (int) spinner_X.getValue();
				label_X.setText(String.valueOf(spinner_X_value));
			//	canvas.setMarkerLineX1pos(spinner_X_value);
			//	canvas.repaint();
			}
		});
		horizontalBox_1.add(spinner_X);
		
		Component rigidArea_8 = Box.createRigidArea(new Dimension(20, 20));
		rigidArea_8.setMinimumSize(new Dimension(15, 20));
		rigidArea_8.setPreferredSize(new Dimension(15, 20));
		rigidArea_8.setMaximumSize(new Dimension(15, 20));
		horizontalBox_1.add(rigidArea_8);
		
		JLabel lblXMarker_1 = new JLabel("Y2 marker");
		horizontalBox_1.add(lblXMarker_1);
		
		Component rigidArea_6 = Box.createRigidArea(new Dimension(20, 20));
		rigidArea_6.setMinimumSize(new Dimension(15, 20));
		rigidArea_6.setPreferredSize(new Dimension(15, 20));
		rigidArea_6.setMaximumSize(new Dimension(15, 20));
		horizontalBox_1.add(rigidArea_6);
		
		spinner_dY = new JSpinner();
		spinner_dY.setDoubleBuffered(true);
		spinner_dY.setMinimumSize(new Dimension(50, 20));
		spinner_dY.setPreferredSize(new Dimension(50, 20));
		horizontalBox_1.add(spinner_dY);
		
		Component rigidArea_7 = Box.createRigidArea(new Dimension(20, 20));
		rigidArea_7.setMinimumSize(new Dimension(15, 20));
		rigidArea_7.setPreferredSize(new Dimension(15, 20));
		rigidArea_7.setMaximumSize(new Dimension(15, 20));
		horizontalBox_1.add(rigidArea_7);
		
		JLabel lblXMarker_2 = new JLabel("X2 marker");
		horizontalBox_1.add(lblXMarker_2);
		
		Component rigidArea_9 = Box.createRigidArea(new Dimension(20, 20));
		rigidArea_9.setMinimumSize(new Dimension(15, 20));
		rigidArea_9.setPreferredSize(new Dimension(15, 20));
		rigidArea_9.setMaximumSize(new Dimension(15, 20));
		horizontalBox_1.add(rigidArea_9);
		
		spinner_dX = new JSpinner();
		spinner_dX.setDoubleBuffered(true);
		spinner_dX.setPreferredSize(new Dimension(50, 20));
		spinner_dX.setMinimumSize(new Dimension(40, 20));
		horizontalBox_1.add(spinner_dX);
		Box horizontalBox = Box.createHorizontalBox();
		sl_panel.putConstraint(SpringLayout.WEST, horizontalBox, 10, SpringLayout.WEST, panel);
		sl_panel.putConstraint(SpringLayout.EAST, horizontalBox, -10, SpringLayout.EAST, panel);
		horizontalBox.setAlignmentX(0.0f);
		sl_panel.putConstraint(SpringLayout.NORTH, horizontalBox, 42, SpringLayout.NORTH, panel);
		panel.add(horizontalBox);
		
		b0 = new JButton("Plotta Kurva");
		b0.setDoubleBuffered(true);
		b0.setPreferredSize(new Dimension(130, 23));
		b0.setMaximumSize(new Dimension(130, 23));
		b0.addActionListener(new Listener().new PlotFunction());
		horizontalBox.add(b0);
		
		Component rigidArea_2 = Box.createRigidArea(new Dimension(20, 20));
		rigidArea_2.setMaximumSize(new Dimension(22, 20));
		rigidArea_2.setMinimumSize(new Dimension(22, 20));
		rigidArea_2.setPreferredSize(new Dimension(22, 20));
		horizontalBox.add(rigidArea_2);
		
		b1 = new JButton("Radera Kurva");
		b1.setDoubleBuffered(true);
		b1.setPreferredSize(new Dimension(130, 23));
		b1.setMaximumSize(new Dimension(130, 23));
		b1.addActionListener(new Listener().new Repaint());
		horizontalBox.add(b1);
		
		Component rigidArea_3 = Box.createRigidArea(new Dimension(20, 20));
		rigidArea_3.setMaximumSize(new Dimension(22, 20));
		rigidArea_3.setMinimumSize(new Dimension(22, 20));
		rigidArea_3.setPreferredSize(new Dimension(22, 20));
		horizontalBox.add(rigidArea_3);
		
		b2 = new JButton("Render Canvas");
		b2.setDoubleBuffered(true);
		b2.setPreferredSize(new Dimension(130, 23));
		b2.setMaximumSize(new Dimension(130, 23));
		b2.addActionListener(new Listener().new Render());
		horizontalBox.add(b2);
		
		JButton b3 = new JButton("Avsluta");
		b3.setDoubleBuffered(true);
		b3.setMinimumSize(new Dimension(72, 23));
		b3.setPreferredSize(new Dimension(130, 23));
		b3.setMaximumSize(new Dimension(130, 23));
		b3.addActionListener(new Listener().new Avbryt());
		
		Component rigidArea_4 = Box.createRigidArea(new Dimension(20, 20));
		rigidArea_4.setMaximumSize(new Dimension(22, 20));
		rigidArea_4.setMinimumSize(new Dimension(22, 20));
		rigidArea_4.setPreferredSize(new Dimension(22, 20));
		horizontalBox.add(rigidArea_4);
		horizontalBox.add(b3);
		
		JPanel panel_1 = new JPanel();
		panel_1.setOpaque(false);
		panel_1.setForeground(new Color(0, 0, 0));
		panel_1.setBackground(new Color(255, 255, 255));
		panel_1.setBounds(612, 376, 165, 20);
		getContentPane().add(panel_1);
		panel_1.setLayout(null);
		
		label_Y = new Label(String.valueOf(SPINNER_Y_STARTVALUE));
		label_Y.setFont(new Font("Arial Black", Font.BOLD, 15));
		label_Y.setAlignment(Label.CENTER);
		label_Y.setForeground(Color.BLACK);
		label_Y.setBackground(Color.YELLOW);
		label_Y.setBounds(0, 0, 80, 20);
		panel_1.add(label_Y);
		
		label_X = new Label(String.valueOf(SPINNER_X_STARTVALUE));
		label_X.setForeground(Color.BLACK);
		label_X.setFont(new Font("Arial Black", Font.BOLD, 15));
		label_X.setBackground(Color.YELLOW);
		label_X.setAlignment(Label.CENTER);
		label_X.setBounds(85, 0, 80, 20);
		panel_1.add(label_X);	
		CanvasGraph canvas =  new CanvasGraph(5,5,CANVAS_WIDTH,CANVAS_HEIGHT);
		getContentPane().add(canvas);
		//getContentPane().add(drawpanel);
		// getContentPane().add(canvas);
		
	}
}
Canvas att rita rektanglar med innehåll i...

Kod: Markera allt

import java.awt.AlphaComposite;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;

public class CanvasGraph extends Canvas {
	private static final long serialVersionUID = 1L;
	public static final int AXIS_MARGIN = 68;		// totala marginalen ovan+under och vänster+höger
	public static final int X_MARKERS_SPACE = 20;	// antal pixlar mellan varje markör på x-axeln
	public static final int Y_MARKERS_SPACE = 10;	// sätter steglängden hos markörer 
	public static final int MARKER_LENGTH = 1;		// markörernas halva längd
	public static final int SCALEFACTOR_Y = 100;	// y-axeln ska visa 100ggr mindre värden än dess längd i pixlar
	
	private int canvasWidth;
	private int canvasHeight;
	private ImageA imgA;
	private ImageB imgB;
	private int rule;
	private static Point2D origo;
	/*
	 * Konstruktor. Skapar en canvas med höjd, bredd och placeras
	 * med offset i x- och y-led i den behållare där den ingår.
	 * Ritar en Canvas som buffrade bilder sedan placeras på.
	 */
	public CanvasGraph(int offsetX, int offsetY,int width, int height) {
		canvasWidth = width;
		canvasHeight = height;
		//setBackground(Color.WHITE);
		setBounds(offsetX, offsetY, width, height);
		rule = AlphaComposite.SRC_OVER;
		imgA = new ImageA(canvasWidth,canvasHeight,Color.WHITE); 						 // skapa en buffrad bild med x-y-axel
		imgB = new ImageB(canvasWidth-AXIS_MARGIN,canvasHeight-AXIS_MARGIN,Color.BLUE); // skapa en buffrad bild med plottad funktion
	}
	public void paint(Graphics gr) {
		super.paint(gr);
		Graphics2D g = (Graphics2D) gr;	
		g.drawImage(imgA, null, 0, 0);									// rita den buffrade bilden
		float alpha = 0.5f;												// genomskinlighetsgrad för nästa bild
		AlphaComposite comp = AlphaComposite.getInstance(rule, alpha);
		g.setComposite(comp);		
		g.drawImage(imgB, null, (int) origo.getX(),AXIS_MARGIN/2);		// rita den buffrade bilden
		g.dispose();
	}
	public static void setOrigo(Point2D origo) {
		CanvasGraph.origo = origo;
	}
	public static Point2D getOrigo() {
		return origo;
	}
}
Buffrad bild som innehåller axlar...

Kod: Markera allt

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
/*
 * Skapar en buffrad bild som ligger i botten av ett lager med flera bilder.
 * Bilden består av en färgad rektangel som det går att rita i.
 * Denna basbild innehåller en skalad x- och y-axel.
 */
public class ImageA extends BufferedImage {
	private Graphics2D g;
	private Rectangle2D rek;
	private int canvasWidth;
	private int canvasHeight;
	private int xAxisLength;
	private int yAxisLength;
	private int xAxisStart;
	private int xAxisEnd;
	private int yAxisStart;
	private int yAxisEnd;
	private Point2D xEnd;
	private Point2D yEnd;
	private Point2D origo;
	private int numberOfxMarkers;
	private int numberOfyMarkers;
	public ImageA(int width, int height, Color color) {
		super(width, height, BufferedImage.TYPE_INT_ARGB);
		canvasWidth = width;
		canvasHeight = height;		
		g = this.createGraphics();
		g.setStroke(new BasicStroke(1.0f));
		rek = new Rectangle2D.Double(0,0,width,height);
		g.setPaint(color);
		g.fill(rek);
		g.draw(rek);
		g.setPaint(Color.BLACK);
		drawAxis();
		drawMarkers();
		g.dispose();
	}
	private void drawMarkers() {
		numberOfxMarkers = xAxisLength/CanvasGraph.X_MARKERS_SPACE;
		numberOfyMarkers = yAxisLength/CanvasGraph.Y_MARKERS_SPACE;
		int dx = xAxisLength/numberOfxMarkers;
		int dy = yAxisLength/numberOfyMarkers;
		int xs = xAxisStart;
		int xe = xAxisEnd;
		int ys = yAxisStart;
		int ye = yAxisEnd;
		Font font = new Font("SansSerif", Font.PLAIN, 14);
		AffineTransform affineTransform = new AffineTransform();
		affineTransform.rotate(Math.toRadians(90), 0, 0);		
		Font rotatedFont = font.deriveFont(affineTransform);
		g.setFont(rotatedFont);
		for(int i=xs;i<=xe;i+=dx) {		// börja rita x-markörer från origo
			drawXMarker(i,i-xs);
		}
		font = new Font("SansSerif", Font.PLAIN, 11);
		affineTransform = new AffineTransform();
		affineTransform.rotate(Math.toRadians(0), 0, 0);		
		rotatedFont = font.deriveFont(affineTransform);
		g.setFont(rotatedFont);
		for(int i=ys;i>=ye;i-=dy) {		// börja rita y-markörer från origo
			drawYMarker(i,(ys-i)/100.0);
		}
	}
	/*
	 * Ritar markörer utmed x-axeln på de positioner som anges av
	 * parametern xpos.
	 */
	private void drawXMarker(int xpos,int scaleNumber) {
		String s = String.valueOf(scaleNumber);
		Point xm1 = new Point(xpos,(int)origo.getY()+CanvasGraph.MARKER_LENGTH);
		Point xm2 = new Point(xpos,(int)origo.getY()-CanvasGraph.MARKER_LENGTH);
		Line2D.Double marker = new Line2D.Double(xm1,xm2);
		g.draw(marker);
		drawXScale(s,xpos-3,(int)(origo.getY()+5));
	}
	/*
	 * Ritar markörer utmed y-axeln på de positioner som anges av
	 * parametern ypos.
	 */
	private void drawYMarker(int ypos, double scaleNumber) {
		String s = String.valueOf(scaleNumber);
		Point ym1 = new Point((int)origo.getX()-CanvasGraph.MARKER_LENGTH,ypos);
		Point ym2 = new Point((int)origo.getX()+CanvasGraph.MARKER_LENGTH,ypos);
		Line2D.Double marker = new Line2D.Double(ym1,ym2);
		g.draw(marker);
		drawYScale(s,(int)(origo.getX()),ypos);
	}
	/*
	 * Graderar x-axeln med tal 
	 */
	private void drawXScale(String s, int xpos, int ypos) {	
		g.setPaint(Color.BLUE);
		g.drawString(s, xpos-1, ypos+1);
	}
	/*
	 * Graderar y-axeln med tal
	 */
	private void drawYScale(String s, int xpos, int ypos) {	
		g.setPaint(Color.RED);
		g.drawString(s, xpos-20, ypos+3);
	}
	private void drawAxis() {
		xAxisLength = canvasWidth - CanvasGraph.AXIS_MARGIN;				
		yAxisLength = canvasHeight- CanvasGraph.AXIS_MARGIN;				
		xAxisStart = canvasWidth - xAxisLength - CanvasGraph.AXIS_MARGIN/2; 	
		yAxisEnd = canvasHeight - yAxisLength - CanvasGraph.AXIS_MARGIN/2;											
		yAxisStart = canvasHeight - CanvasGraph.AXIS_MARGIN/2;		
		xAxisEnd = xAxisLength + xAxisStart;
		CanvasGraph.setOrigo(new Point(xAxisStart,yAxisStart));
		origo = CanvasGraph.getOrigo();
		xEnd = new Point(xAxisEnd,yAxisStart);
		yEnd = new Point(xAxisStart,yAxisEnd);
		Line2D.Double xAxel = new Line2D.Double(origo,xEnd);
		Line2D.Double yAxel = new Line2D.Double(origo, yEnd);
		g.draw(xAxel);
		g.draw(yAxel);
	}
}
Buffrad bild som håller den plottade kurvan...

Kod: Markera allt

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
/*
 * Skapar en buffrad bild.
 * Bilden består av en färgad rektangel som det går att rita i.
 * Denna bild innehåller en plottad kurva.
 */
public class ImageB extends BufferedImage {
	private Graphics2D g;
	private Rectangle2D rek;
	private Point2D origo;
	public ImageB(int width, int height, Color color) {
		super(width, height, BufferedImage.TYPE_INT_ARGB);
		origo = CanvasGraph.getOrigo();
		g = this.createGraphics();
		g.setStroke(new BasicStroke(1.0f));
		rek = new Rectangle2D.Double(0,0,width,height);
		g.setPaint(color);
		g.fill(rek);	
		g.draw(rek);
		g.setPaint(Color.BLACK);
		plotFunction(SwingWindow.A,SwingWindow.B,SwingWindow.C);
		g.dispose();
	}
	/*
	 * Ritar en funktion y(x) i x-y-grafen. y(x) = a + bx + cx^2 
	 * y = 2.31 - 0.0047*R + 1.93*10^-6*R^2
	 */
	private void plotFunction(double a, double b, double c) {
		double x1 = 0;
		double y1 = 0;
		double x2 = 0;
		double y2 = 0;	
		while(y2>=0) {		
			y2 = (a + b*x2 + c*Math.pow(x2, 2))*100;
			g.drawLine(x(x1), y(y1), x(x2), y(y2));
			x1 = x2;
			y1 = y2;
			x2 = x2+1;
		}
	}
	/*
	 * Parametern x refererar till en x-koordinat med ett origo som har x=0 och y=0
	 * Returnerar den absoluta x-koordinaten i förhållande till det origo
	 * som ritats i canvas med de faktiska x- och y-koordinaterna.
	 */
	private int x(double x) {
		return (int)(origo.getX()+x-CanvasGraph.AXIS_MARGIN/2);
	}
	/*
	 * Parametern y refererar till en y-koordinat med ett origo som har x=0 och y=0
	 * Returnerar den absoluta y-koordinaten i förhållande till det origo
	 * som ritats i canvas med de faktiska x- och y-koordinaterna.
	 */
	private int y(double y) {
		return (int)(origo.getY()-y-CanvasGraph.AXIS_MARGIN/2);
	}

}
En lyssnarklass för knappar fast den nyttjar jag inte till något vettigt ännu...

Kod: Markera allt

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;

public class Listener extends JFrame {
	private static final long serialVersionUID = 1L;
	public Listener() {
		
	}

	public class Avbryt implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			System.exit(0);			
		}		
	}
	
	public class PlotFunction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
		//	SwingWindow.getCanvas().plotFunction(SwingWindow.A,SwingWindow.B,SwingWindow.C);
		}		
	}
	
	public class Repaint implements ActionListener {
		public void actionPerformed(ActionEvent e) {
		//	SwingWindow.getCanvas().repaint();		
		}		
	}
	public class Render implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			System.out.println("RENDER");
					
		}		
	}
}
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
AndLi
Inlägg: 17045
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Mätapplikation med Arduino och Java

Inlägg av AndLi »

Projektet går ut på att uppfinna hjulet själv igen?
Annars finns det ju massor av färdiga grafritare, men det är alltid bra att göra en första själv, så man inser hur komplext det faktiskt är...
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Ja jo lite så kan man ju tycka att det är.

Sedan tycker jag själv att det är kul att lära sig det här och
kunna få det precis som jag själv vill ha det.

Det finns sedan oändligt med möjligheter om man skulle
behärska det mesta av Javabiblioteken med grafik, men det
tar sin tid så klart.

Jag är inne på att försöka simulera fysikaliska förlopp med grafik,
så jag läser lite i en bok med fysik för spel men jag har tyvärr
inte läst all den matematiken med tredimensionella vektorer
och tensorberäkning som ofta ingår.
Användarvisningsbild
4kTRB
Inlägg: 18283
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Ett kort att ansluta till 2 av Arduinos analoga ingångar.

Då olika NTC-värden ska mätas behövs olika bryggor för att
få rätt spänningar så därför valde jag att ha plug-in-bryggor.

Den nedan är avsedd för ett NTC runt 560 ohm.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Skriv svar