Mätapplikation med Arduino och Java

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

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Håller ju på med att lära mig C++ för att lättare komma igång med Arduino i detta projekt men
tjuvstartade lite med Eclipse och ett av de plug-in som finns.
Efter en del huvudbry så verkar det faktiskt fungera nu.

En lite fundering, när koden laddas upp till Arduino fås en översikt av minnesanvändning med mera
i konsolen på Eclipse. Där finns att läsa att 1000 byte har skrivits till flash. Så jag letade upp
en (den enda jag hittade) hex-fil som genereras och laddade upp den i en HEX-analysator online.

Hex-analysator säger att filen består av 2832 byte.

De extra byte som ingår, kommer de från formatet?
Motorola har ju S-format till exempel.
Analysatorn fixade inte att tala om vilket format det var om det nu finns något vill säga.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Liten följdfråga är .... har jag någon direkt nytta av den hex-filen som Eclips genererat?
Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Leker en del med Arduino nu. Testat en timer-klass som kan vara användbar
om fler pinnar ska jobba med olika saker. Lite luddigt tycker jag dock att
beskrivningen av funktionerna är såsom stop() till exempel.
Sedan verkar det som man måste deklarera funktioner som man kodar,
som doSomething i koden nedan. Tycker mig ha sett åtskilliga exempel-koder
där man inte gjort så men det kanske är för att korta ned koden.

Kod: Markera allt

#include <Arduino.h>
#include "Timer/Timer.h"

Timer t1;
Timer t2;
int tickEvent;
int LEDEvent;
int LEDEvent2;
void doSomething(void* context);
char w[] = {'A','B','C','D','E'};
void* ch = w;
int index = 0;

void setup() {
	Serial.begin(9600);
	pinMode(13, OUTPUT);
	tickEvent = t1.every(1000, doSomething, ch);
	LEDEvent = t1.oscillate(13, 75, HIGH);
	LEDEvent2 = t2.oscillate(13, 150, HIGH);
}

void loop() {
	while(index <=40){
		t1.update();
		if(index == 15){
			t1.stop(LEDEvent);
		}
		if(index >= 15){
			t2.update();
		}
	}
	t1.stop(tickEvent);
	t1.stop(LEDEvent);
	t2.stop(LEDEvent2);
	digitalWrite(13,LOW);
	Serial.end();
}

void doSomething(void* ch)
{
	char* p = (ch + index % 4);
	Serial.write(*p);
	Serial.print(" Index = ");
	Serial.print(index);
	Serial.print("  millisekunder = ");
	Serial.println(millis());
	index++;
}
Användarvisningsbild
Klas-Kenny
Inlägg: 11292
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Re: Mätapplikation med Arduino och Java

Inlägg av Klas-Kenny »

Du måste inte skriva funktionsprototyper, men om du inte gör det måste funktionen skrivas ovanför där du anropar den. Koden läses ovanifrån, och om man då anropar en funktion som deklareras senare i koden känns den inte igen.
Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Har testat en hel del nu med att samla in data via två ADC-pinnar (A0 och A1, A och B i schemat) från en bryggkoppling.
Jag sätter ett intervall på 10mV som det får diffa på för att anse att bryggan är i balans.
När den är det så blir skylten "Vid Balans Tryck Ok-->" grön. Jag testar med en trimpot och
ser att det fungerar. Men sedan har jag två så kallade progressbars (de 2 gråa fälten under kalibrerings-sekvensen)
som ska agera som indikator på när det blir ännu bättre intrimmat.
När väl det är utfört ansluter jag två kända resistorer i bryggan för att få kurvans ekvation varifrån sedan
NTC-motståndets värde beräknas. Det blir en rät linje y = kx + m.
När väl bryggan är intrimmad så kan jag påbörja uppvärmning av ett aluminiumblock där temperaturen mäts
och spänningen från bryggan som via formeln ger NTC-motståndets värde.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Arrduinokoden består av ett menyvalssystem som kör en loop.
När olika kommandon skickas från Java-gui så utförs de olika
rutinerna. Mer funktioner kommer läggas till senare.

Kod: Markera allt

#include <Arduino.h>

//Koden efterliknar en datainsamling av temperatur och NTC-motstånd
//Javaprogrammet har testats och utvecklats mot denna programkörning

// ****************************************************
//   variabler och konstanter för kalibrering av brygga
// ****************************************************
bool alertFlag;
int analogPinA = A0;                  			// bryggans anslutning A
int analogPinB = A1;                  			// bryggans anslutning B
int ohm = 500;
const int NUMBER_OF_SAMPLES = 100;            	// medelvärdesbilda AD-omvandla många gånger
const double DIFF_MAX = 0.01;              		// tolerans 10 mV för att anse att bryggan är i balans
const double BIT_VOLTAGE_FACTOR = 0.004888;     // volt per bit för ad-omvandlare (5.0/1023)

void zeroAdjustAlert(double);
void averageData(double&, double&, double&);
void bridgeZeroAdjust(void);
// ****************************************************
// 0 är startsignal för datainsamling i Arduinos meny
// 1 är startsignal för nollkalibrering av brygga i Arduinos meny
// 2 är startsignal för datainsamling i Arduinos meny
// 3 är startsignal för datainsamling i Arduinos meny
// 4 är Exit i Arduinos meny Serial().end;
// 100 abryter while-loop i ntcMeasurement()
// 200 abryter while-loop i bridgeZeroAdjust()
// Z indikerar att bryggan är i balans i zeroAdjustAlert-funktionen
// X indikerar att bryggan är i obalans i zeroAdjustAlert-funktionen

// the setup function runs once when you press reset or power the board

int celcius;
int inByte = -1;                    			// incoming serial byte

void ntcMeasurement();
void bridgeZeroAdjust();
void setCelcius(int);
int getCelcius();

void setup() {
	Serial.begin(19200);
	setCelcius(0);
	pinMode(LED_BUILTIN, OUTPUT);
	digitalWrite(LED_BUILTIN, LOW);     		// används för att testa programmet
	while (!Serial) {
		; 										// wait for serial port to connect. Needed for native USB
	}
}

// En loop med meny. Data skickas från JAVA-datorn och olika saker utförs.
// Inga av de funktioner som väljs att exekveras körs som trådar på Arduino
// så för att menysystems-loopen ska kunna hantera nästa kommando måste
// den funktion som pågår först avslutas, innan dess case-break; tillåter
// fler menyval. I GUI så kan inte fler menyval utföras förrens det pågående
// avslutats, undantag gäller EXIT för programavslut.
void loop()
{
	if (Serial.available() > 0)
	{
		inByte = Serial.read();
		switch (inByte){
		case 0:                 				 // en NTC-mätning är begärd
			ntcMeasurement();         			 // funktion med while-loop, tar en stund
			digitalWrite(LED_BUILTIN, LOW);   	 // visuell indikering på att NTC-mätning är utförd
			break;               				 // först nu kan nya menyval utvärderas
		case 1:
			bridgeZeroAdjust();        			 // en loop som hela tiden indikerar om bryggan är nolltrimmad eller ej
			digitalWrite(13, LOW);
			break;               		 		 // fortsätt i meny-loop när bridgeZeroAdjust() har avslutats
		case 2:

			break;
		case 3:

			break;
		case 4:
			digitalWrite(LED_BUILTIN, HIGH);
			delay(3000);
			Serial.end();           			  // nedkoppling av seriekommunikation/com-port
			break;
		default:
			digitalWrite(LED_BUILTIN, LOW);
		}
	}
	delay(100);
	digitalWrite(LED_BUILTIN, HIGH);              // visuell indikering att Arduino är aktiv i menyloopen
	delay(100);
	digitalWrite(LED_BUILTIN, LOW);
}

/*
 * En loop som mäter obalansen i NTC-mätbryggan.
 * Två spänningar från två ADC-ingångar mäts och medelvärdesbildas.
 * Sedan tas differensen av dessa spänningar och utifrån denna differens
 * avgörs om bryggan anses vara i balans / nolltrimmad. Arduino skickar
 * signal till Java-datorn som i sin tur indikerar balans eller obalans i GUI.
 * Loopen avbryts manuellt från GUI med tryck på en knapp.
 */
void bridgeZeroAdjust(){
	alertFlag = true;
	bool breakFlag = true;
	double averageVoltA = 0.0;
	double averageVoltB = 0.0;
	double vDiff = 0.0;
	while(breakFlag){
		averageData(averageVoltA, averageVoltB, vDiff);  // mät obalansen medeelvärdesbilda en aning
		zeroAdjustAlert(vDiff);                          // indikera om en nolljustering utförts
		delay(50);                                       // dra ned tempot
		if (Serial.available() > 0){                     // kommando sänt? Avbryt balanstrimmning av brygga?
			if(Serial.read() == 200){                    // 200 avbryter while-loop
				breakFlag = false;
			}
		}
	}
}

/*
 * Argumenten voltA, voltB och voltDiff är call by reference
 */
void averageData(double& voltA, double& voltB, double& voltDiff){
	double sumA = 0;
	double sumB = 0;
	for(int i = 0; i < NUMBER_OF_SAMPLES; i++){
		sumA += (analogRead(analogPinA)* BIT_VOLTAGE_FACTOR);
		sumB += (analogRead(analogPinB)* BIT_VOLTAGE_FACTOR);
	}
	voltA = sumA/NUMBER_OF_SAMPLES;
	voltB = sumB/NUMBER_OF_SAMPLES;
	voltDiff = voltA-voltB;
}

/*
 * Om bryggan är i balans inom given tolerans så skicka info till Java-datorn
 * att balansvillkor är uppfyllt. I GUI indikeras att bryggan är balanstrimmad.
 */
void zeroAdjustAlert(double voltageDiff){
	if(fabs(voltageDiff) <= DIFF_MAX){    					// om spänningar är lika inom tolerans så
		digitalWrite(13, HIGH);       						// ALERT!
		Serial.write("Z");          						// Meddela Java-datorn att bryggan är i balans
		Serial.write('\n');
	}
	else{
		digitalWrite(13, LOW);       	 					// annars så håll lysdioden släckt
		Serial.write("X");          						// Meddela Java-datorn att bryggan är i obalans
		Serial.write('\n');
	}
}

void ntcMeasurement(){
	setCelcius(24);
	int temp = getCelcius();
	digitalWrite(LED_BUILTIN, HIGH);     	 				// visuell indikering
	Serial.write("START");
	Serial.write("\n");
	while (getCelcius() < 101) {
		Serial.print(getCelcius());
		Serial.write("  ");
		Serial.print(ohm);
		Serial.write('\n');
		delay(800);
		setCelcius(temp++);
		ohm = -5.9 * getCelcius() + 635;
		if (Serial.available() > 0){      					// kommando sänt?
			if(Serial.read() == 100){     					// 100 avbryter while-loop
				setCelcius(101);
			}
		}
	}
}

void setCelcius(int temp){
	celcius = temp;
}

int getCelcius(){
	return celcius;
}


Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Lärde mig eller ja återupptäckte kanske är mer rätt ord då jag någon gång i forntiden hade koll på detta att det går använda sig av inre klasser på ett smidigt sätt för att dela upp javakoden i fler filer/klasser och undvika att ha för mycket kod i main. Jag utnyttjar det till händelsehanterarna för de olika knapparna i GUI.

När en knapp skapats såsom t.ex. startknappen för att nolltrimma bryggan så behöver jag inte lägga till koden för hela mouseUp händelsen i main-koden utan då använder jag en separat klass i en annan fil där alla mouseUp händelser finns för varje knapp i GUI.

Ex.

Kod: Markera allt

START_A = new Button(composite_3, SWT.CENTER);
		START_A.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		START_A.setFont(SWTResourceManager.getFont("Segoe UI", 9, SWT.BOLD));


		START_A.addMouseListener(new ButtonMouseListener().new START_A_Listener());


		START_A.setBounds(199, 0, 52, 45);
		START_A.setText("START");

Kod: Markera allt

import java.io.DataOutputStream;
import java.io.IOException;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.wb.swt.SWTResourceManager;
/*
 * Samtliga knappar i GUI reagerar på ett MouseUpEvent i händelsehanteraren.
 * Kapparna identifieras i metoden mouseUp nedan och respektive knapps kod exekveras.
 */
public class ButtonMouseListener extends MouseAdapter {
	private TextFile textFile;	
	public ButtonMouseListener() {
		this.textFile = NTC.getTextFile();
	}
	/*
	 * 
	 */
	public class START_Listener implements MouseListener{
		public void mouseDoubleClick(MouseEvent e) {}
		public void mouseDown(MouseEvent e) {}
		public void mouseUp(MouseEvent e) {
			if(NTC.getArduinoConnectedFlag()) {										// se till att Arduino finns uppkopplad
				NTC.resetTimer();
				textFile.setTextFileName(NTC.txtDatatxt.getText()); 				// hämta text från textfält med önskat filnamn				
				NTC.resetLedDisplay();
				NTC.buttonStart.setEnabled(false);
				if(NTC.threadControllerThread[4].isAlive()) {
					NTC.threadControllerThread[4] = new Thread (NTC.threadController[4]);
				}
				try {				
					NTC.threadControllerThread[4].start();							// starta trådkontrollern
					System.out.println(NTC.threadControllerThread[4].getName() + " är startad");
				}
				catch(IllegalThreadStateException itse) {
					System.out.println("IllegalThreadStateException");
				}	
			}
		}
	}
	/*
	 * 
	 */
	public class STOPP_Listener implements MouseListener{
		public void mouseDoubleClick(MouseEvent e) {}
		public void mouseDown(MouseEvent e) {}
		public void mouseUp(MouseEvent e) {
			if (NTC.threadControllerThread[4].isAlive()) {		// signalera Stopp till Arduino-inläsningen
				try {											// avbryt trådkontrollern som i sin tur avbryter
					NTC.threadControllerThread[4].interrupt();	// inäsning av data från Arduinon
					System.out.println(NTC.threadControllerThread[4].getName() + " är avbruten");
				}
				catch(SecurityException se) {
					System.out.println("SecurityException");						
				}
			}			
		}
	}
	/*
	 * 
	 */
	public class EXIT_Listener implements MouseListener{
		public void mouseDoubleClick(MouseEvent e) {}
		public void mouseDown(MouseEvent e) {}
		public void mouseUp(MouseEvent e) {
			System.out.println("EXIT-EXIT-EXIT-EXIT-EXIT");
			if(NTC.getArduinoConnectedFlag()) {
				(new Thread () {											// en tråd skriver ett EXIT-kommando till Arduino
					DataOutputStream javaToArduinoOut = null;
					public void run() {
						javaToArduinoOut = new DataOutputStream(Test.getSerialPort().getOutputStream());
						try {
							javaToArduinoOut.writeByte(NTC.EXITZEROADJUST);	// avbryt eventuell nolltrim-loop
							javaToArduinoOut.writeByte(NTC.EXITNTCMEASURE);	// avbryt eventuell ntc-mät-loop
							javaToArduinoOut.writeByte(NTC.EXIT);			// menyval för Exit i Arduinos meny
						} catch (IOException e1) {
							e1.printStackTrace();
						}				
						try {
							javaToArduinoOut.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
						try {
							NTC.threadControllerThread[0].interrupt();
							NTC.threadControllerThread[1].interrupt();
							NTC.threadControllerThread[2].interrupt();
							NTC.threadControllerThread[3].interrupt();
							NTC.threadControllerThread[4].interrupt();
							NTC.threadControllerThread[5].interrupt();
						}
						catch (SecurityException se){
							System.out.println("SecurityException");	
						} 
					}
				}).start();
			}								
			try {
				Thread.sleep(500);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			System.out.println("EXIT");				
			NTC.shlNtc.close();
			//	display.close();
			SWTResourceManager.dispose();
			System.exit(0);			
		}
	}
	/*
	 * 
	 */
	public class OK_ABC_Listener implements MouseListener{
		public void mouseDoubleClick(MouseEvent e) {}
		public void mouseDown(MouseEvent e) {}
		public void mouseUp(MouseEvent e) {		
			NTC.threadControllerThread[1].interrupt();						// avbryt samtliga kalibreringstrådar
			NTC.threadControllerThread[2].interrupt();
			NTC.threadControllerThread[3].interrupt();
			NTC.threadControllerThread[5].interrupt();
			if(NTC.getArduinoConnectedFlag()) {								// se till att Arduino finns uppkopplad	
				NTC.threadStack.clearStack();								// lägg upp ordning för kalibreringsprocedur				
				NTC.threadStack.push("F");									// RrefB trim klart/OK
				NTC.threadStack.push("E");									// trimma med RrefB
				NTC.threadStack.push("D");									// RrefA trim klart/OK
				NTC.threadStack.push("C");									// trimma med RrefA
				NTC.threadStack.push("B");									// nolltrim klart/OK
				NTC.threadStack.push("A");									// start nolltrim				
			}
			NTC.OK_ABC.setForeground(SWTResourceManager.getColor(255, 255, 204));
			NTC.OK_ABC.setBackground(SWTResourceManager.getColor(204, 51, 51));
			System.out.println("NTC.OK_ABC");			
		}		
	}
	/*
	 * 
	 */
	public class START_A_Listener implements MouseListener{
		public void mouseDoubleClick(MouseEvent arg0) {}
		public void mouseDown(MouseEvent arg0) {}
		public void mouseUp(MouseEvent e) {
			if(NTC.getArduinoConnectedFlag()) {								// se till att Arduino finns uppkopplad				
				if(NTC.threadStack.lookAtTheTopOfStack() == "A") {
					NTC.progressBarA.setSelection(0);
					NTC.progressBarB.setSelection(0);
					NTC.threadStack.pop();
					if(NTC.threadControllerThread[1].isAlive())
						NTC.threadControllerThread[1].interrupt();
						NTC.threadControllerThread[5].interrupt();
						NTC.threadControllerThread[1] = new Thread (NTC.threadController[1]);
						NTC.threadControllerThread[5] = new Thread (NTC.threadController[5]);
					try {									
						NTC.threadControllerThread[1].start();				// starta trådkontrollern
						NTC.threadControllerThread[5].start();
						NTC.OK_ABC.setForeground(SWTResourceManager.getColor(0, 0, 0));
						NTC.OK_ABC.setBackground(SWTResourceManager.getColor(250, 250, 250));
					}
					catch(IllegalThreadStateException itse) {
						System.out.println("IllegalThreadStateException");
					}
				}
			}
			System.out.println("NTC.START_A");			
		}
	}
	/*
	 * 
	 */
	public class OK_A_Listener implements MouseListener{
		public void mouseDoubleClick(MouseEvent e) {}
		public void mouseDown(MouseEvent e) {}
		public void mouseUp(MouseEvent e) {
			if(NTC.threadStack.lookAtTheTopOfStack() == "B") {
				NTC.threadStack.pop();
				try {																			// avbryt trådkontrollern
					NTC.threadControllerThread[1].interrupt();	
					NTC.threadControllerThread[5].interrupt();
				}
				catch(SecurityException se) {
					System.out.println("SecurityException");						
				}
				NTC.progressBarA.setSelection(0);
				NTC.progressBarB.setSelection(0);
			}
			System.out.println("NTC.OK_A");
		}
	}
	/*
	 * 
	 */
	public class START_B_Listener implements MouseListener{
		public void mouseDoubleClick(MouseEvent e) {}
		public void mouseDown(MouseEvent e) {}
		public void mouseUp(MouseEvent e) {
			if(NTC.getArduinoConnectedFlag()) {													// se till att Arduino finns uppkopplad
				if(NTC.threadStack.lookAtTheTopOfStack() == "C") {
					NTC.threadStack.pop();
					if(NTC.threadControllerThread[2].isAlive())
						NTC.threadControllerThread[2].interrupt();
						NTC.threadControllerThread[2] = new Thread (NTC.threadController[2]);
					try {																		// och att trådstart sker i rätt ordning
						NTC.threadControllerThread[2].start();									// innan trådkontrollern startas							
					}
					catch(IllegalThreadStateException itse) {
						System.out.println("IllegalThreadStateException");
					}
				}
			}
			System.out.println("NTC.START_B");
		}
	}
	/*
	 * 
	 */
	public class OK_B_Listener implements MouseListener{
		public void mouseDoubleClick(MouseEvent e) {}
		public void mouseDown(MouseEvent e) {}
		public void mouseUp(MouseEvent e) {
			if(NTC.threadStack.lookAtTheTopOfStack() == "D"){
				NTC.threadStack.pop();
				try {																			// avbryt trådkontrollern
					NTC.threadControllerThread[2].interrupt();	
				}
				catch(SecurityException se) {
					System.out.println("SecurityException");						
				}					
			}
			System.out.println("NTC.OK_B");
		}
	}
	/*
	 * 
	 */
	public class START_C_Listener implements MouseListener{
		public void mouseDoubleClick(MouseEvent e) {}
		public void mouseDown(MouseEvent e) {}
		public void mouseUp(MouseEvent e) {
			if(NTC.getArduinoConnectedFlag()) {													// se till att Arduino finns uppkopplad
				if(NTC.threadStack.lookAtTheTopOfStack() == "E") {
					NTC.threadStack.pop();							
					if(NTC.threadControllerThread[3].isAlive())
						NTC.threadControllerThread[3].interrupt();
						NTC.threadControllerThread[3] = new Thread (NTC.threadController[3]);
					try {																		// och att trådstart sker i rätt ordning
						NTC.threadControllerThread[3].start();									// innan trådkontrollern startas						
					}
					catch(IllegalThreadStateException itse) {
						System.out.println("IllegalThreadStateException");
					}
				}
			}
			System.out.println("NTC.START_C");
		}
	}
	/*
	 * 
	 */
	public class OK_C_Listener implements MouseListener{
		public void mouseDoubleClick(MouseEvent e) {}
		public void mouseDown(MouseEvent e) {}
		public void mouseUp(MouseEvent e) {
			if(NTC.threadStack.lookAtTheTopOfStack() == "F") {
				NTC.threadStack.pop();
				try {														// avbryt trådkontrollern
					NTC.threadControllerThread[3].interrupt();	
				}
				catch(SecurityException se) {
					System.out.println("SecurityException");						
				}
			}
			System.out.println("NTC.OK_C");
		}
	}
}

Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Trådkontrollern tar emot det objekt som ska köras som tråd och blir väldigt enkel.

De fungerar så här...

Kod: Markera allt

	private Object tc0 = null;						// objekt som ska köras av trådkontrollern
	private Object tc1 = null;						// objekten implementerar interfacet Runnable
	private Object tc2 = null;
	private Object tc3 = null;
	private Object tc4 = null;
	private Object tc5 = null;

	public static ThreadController[] threadController;	// varje tråd har en trådkontroller
	public static Thread[] threadControllerThread;		// varje trådkontroller körs som en tråd

Kod: Markera allt

	/*
	 * Skapar det antal trådkontrollörer som behövs och förbereder dem för start.
	 * Till varje trådkontrollör kopplas ett objekt som trådkontrollören sedan ska starta
	 * i sin run-metod. Klasserna/objekten som ska köras som tråd implementerar interfacet Runnable.
	 * Även trådkontrollern implementerar interfacet Runnable då den också körs som tråd.
	 * För att stoppa en tråd skickas ett interrupt till trådkotrollern som då kastar ett
	 * InterruptedException vari i sin tur ett interrupt utförs på tråden som trådkontrollören
	 * tidigare startat. Tråden avslutas och även trådkontrollören(dess tråd). Trådkontrollören kan
	 * inte startas på nytt utan då måste en ny trådkontrollör skapas om en objekt-tråd ska startas och köras på nytt. 
	 */
	private void setUpThreadControllers() {
		tc0 = new Test(window,display);									// skapa de objekt som ska köras som tråd
		Test.setBaudRate(NTC.DEFAULTBAUDRATE);							// tc0 Anslut Arduino via comport
		tc1 = new Test_1(display);										// tc1 Nolltrimma NTC-brygga
		tc2 = new Test_2();												// tc2 Ta fram ekvation R som funktion av bryggspänning RrefA
		tc3 = new Test_3();												// tc3 Ta fram ekvation R som funktion av bryggspänning RrefB
		tc4 = new CollectArduinoData(window,display);					// tc4 NTC-mätning
		CollectArduinoData.setBreakTemp(NTC.DEFAULTBREAKTEMP);			// default temperatur då mätning ska avbrytas
		tc5 = new MinusZeroPlusMeter(display);

		threadController = new ThreadController[NTC.NUMBEROFTHREADS];
		threadControllerThread = new Thread[NTC.NUMBEROFTHREADS];		
		threadController[0] = new ThreadController(tc0);				// en klass som körs som tråd
		threadController[1] = new ThreadController(tc1);
		threadController[2] = new ThreadController(tc2);
		threadController[3] = new ThreadController(tc3);
		threadController[4] = new ThreadController(tc4);
		threadController[5] = new ThreadController(tc5);

		threadControllerThread[0] = new Thread (threadController[0]); 	// trådkontrollern threadController körs som tråd
		threadControllerThread[1] = new Thread (threadController[1]);
		threadControllerThread[2] = new Thread (threadController[2]);
		threadControllerThread[3] = new Thread (threadController[3]); 
		threadControllerThread[4] = new Thread (threadController[4]);
		threadControllerThread[5] = new Thread (threadController[5]); 
	}

Kod: Markera allt


public class ThreadController implements Runnable {	
	private Object obj;
	private Thread objectThread;
	private static final int   TIMER_INTERVAL = 2000;		// The timer interval in milliseconds
	/*
	 * Konstruktor för en trådkontroller som startar
	 * ett valbart Runnable-objekt/klass i form av en tråd.
	 * Trådkontrollern ligger periodvis i viloläge tills
	 * den blir avbruten. Vid avbrott avbryts den startade
	 * tråden och sedan avslutar trådkontrollern sin while-loop.
	 * Objekttypen som skickas med, när en instans av trådkontrollern skapas,
	 * är en klass som implementerar interfacet Runnable och som alltså är avsedd
	 * att exekveras som en tråd. Varje trådkontroller är bunden till detta objekt.
	 * Ingen startad trå kan startas på nytt utan då måste en ny trådkontroller
	 * för Runnable-objektet skapas på nytt. 
	 */
	public ThreadController(Object object) {
		this.obj = object;
	}

	/**
	 * Startar vald klass som en tråd. Vid interrupt() görs avbrott
	 * i klassobjekten som därefter avslutar sin aktivitet
	 * som tråd. while-loopen nedan avslutas och även run().
	 */
	public void run() {	
		objectThread = new Thread( (Runnable) obj);			// skapar en ny tråd 
		objectThread.start();
		while(true) {
			try {
				Thread.sleep(TIMER_INTERVAL);
			}
			catch(InterruptedException ie) {	
				objectThread.interrupt();
				System.out.println("Avbrott i tråden till " + this.obj.toString());
			}		
		}
	}
}


Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Medelvärdesbildningen av spänningen från AD-omvandlingen gjorde jag om då
det blev lite väl ostabilt, det blev någon typ av interpolation på det sättet
jag valt. Upplösningen per bit är ca: 5mV så jag skickar över obalansen i form
av antalet bitar och presenterar resultatet i GUI i 5mV steg, samma gäller för
de två progress-staplarna. Det fungerar riktigt bra, lätt att se när det är bra trimmat,
ligger man på gränsen av +/-5mV fladdrar staplarna medan närmare noll så blir det stabilt.

För de 2 återstående stegen i kalibreringsproceduren hade det varit fint med digitala potentiometrar
men jag tror jag ska ha någon typ av vridomkopplare eller bara ha byglar på ett pcb och koppla in
monterade fasta motstånd. Det finns ganska många värden på NTC-motstånd och de kommer
kräva olika motståndsvärden i bryggan samt för kalibrering.

Jag testade manuellt att nolltrimma bryggan med 560 ohms-motstånd och sedan ett 470ohms
och ett 68 ohms. Tog fram ekvationen och pluggade in ett 270 ohms motstånd och utifrån
spänningen beräknades 270ohms motståndet. Det blev ett fel på 6 ohm. Felet blir störst på
mitten av kurvan. Sedan kan ju multimetern visa fel också men även enligt en simulering
i LT-spice så ser man att bryggan inte ger en perfekt rak linje, den aviker mest på mitten.

Kod: Markera allt

#include <Arduino.h>

//Koden efterliknar en datainsamling av temperatur och NTC-motstånd
//Javaprogrammet har testats och utvecklats mot denna programkörning

// ****************************************************
//   variabler och konstanter för kalibrering av brygga
// ****************************************************
bool alertFlag;
int analogPinA = A0;                  			// bryggans anslutning A
int analogPinB = A1;                  			// bryggans anslutning B
int ohm;
const int NUMBER_OF_SAMPLES = 250;            	// medelvärdesbilda AD-omvandla många gånger

void zeroAdjustAlert(int);
void averageData(int&, int&, int&);
void bridgeZeroAdjust(void);
// ****************************************************
// 0 är startsignal för datainsamling i Arduinos meny
// 1 är startsignal för nollkalibrering av brygga i Arduinos meny
// 2 är startsignal för datainsamling i Arduinos meny
// 3 är startsignal för datainsamling i Arduinos meny
// 4 är Exit i Arduinos meny Serial().end;
// 100 abryter while-loop i ntcMeasurement()
// 200 abryter while-loop i bridgeZeroAdjust()
// Z indikerar att bryggan är i balans i zeroAdjustAlert-funktionen
// X indikerar att bryggan är i obalans i zeroAdjustAlert-funktionen

// the setup function runs once when you press reset or power the board

int celcius;
int inByte = -1;                    			// incoming serial byte

void ntcMeasurement();
void bridgeZeroAdjust();
void setCelcius(int);
int getCelcius();

void setup() {
	Serial.begin(19200);
	setCelcius(0);
	pinMode(LED_BUILTIN, OUTPUT);
	digitalWrite(LED_BUILTIN, LOW);     		// används för att testa programmet
	while (!Serial) {
		; 										// wait for serial port to connect. Needed for native USB
	}
}

// En loop med meny. Data skickas från JAVA-datorn och olika saker utförs.
// Inga av de funktioner som väljs att exekveras körs som trådar på Arduino
// så för att menysystems-loopen ska kunna hantera nästa kommando måste
// den funktion som pågår först avslutas, innan dess case-break; tillåter
// fler menyval. I GUI så kan inte fler menyval utföras förrens det pågående
// avslutats, undantag gäller EXIT för programavslut.
void loop()
{
	if (Serial.available() > 0)
	{
		inByte = Serial.read();
		switch (inByte){
		case 0:                 				 // en NTC-mätning är begärd
			ntcMeasurement();         			 // funktion med while-loop, tar en stund
			digitalWrite(LED_BUILTIN, LOW);   	 // visuell indikering på att NTC-mätning är utförd
			break;               				 // först nu kan nya menyval utvärderas
		case 1:
			bridgeZeroAdjust();        			 // en loop som hela tiden indikerar om bryggan är nolltrimmad eller ej
			break;               		 		 // fortsätt i meny-loop när bridgeZeroAdjust() har avslutats
		case 2:

			break;
		case 3:

			break;
		case 4:
			digitalWrite(LED_BUILTIN, HIGH);
			delay(3000);
			Serial.end();           			  // nedkoppling av seriekommunikation/com-port
			break;
		default:
			digitalWrite(LED_BUILTIN, LOW);
		}
	}
	delay(100);
	digitalWrite(LED_BUILTIN, HIGH);              // visuell indikering att Arduino är aktiv i menyloopen
	delay(100);
	digitalWrite(LED_BUILTIN, LOW);
}

/*
 * En loop som mäter obalansen i NTC-mätbryggan.
 * Två spänningar från två ADC-ingångar mäts och medelvärdesbildas.
 * Sedan tas differensen av dessa spänningar och utifrån denna differens
 * avgörs om bryggan anses vara i balans / nolltrimmad. Arduino skickar
 * signal till Java-datorn som i sin tur indikerar balans eller obalans i GUI.
 * Loopen avbryts manuellt från GUI med tryck på en knapp.
 */
void bridgeZeroAdjust(){
	alertFlag = true;
	bool breakFlag = true;
	int averageVoltA;
	int averageVoltB;
	int vDiff;
	Serial.write("ZERO");
	Serial.write("\n");
	while(breakFlag){
		averageVoltA = 0;
		averageVoltB = 0;
		vDiff = 0;
		averageData(averageVoltA, averageVoltB, vDiff);  // mät obalansen medeelvärdesbilda en aning
		zeroAdjustAlert(vDiff);                     	 // indikera om en nolljustering utförts
		delay(100);
		if (Serial.available() > 0){                     // kommando sänt? Avbryt balanstrimmning av brygga?
			if(Serial.read() == 200){                    // 200 avbryter while-loop
				breakFlag = false;
			}
		}
	}
}

/*
 * Argumenten voltA, voltB och voltDiff är call by reference
 * Upplösningen är 5/1023 = 4.8888 mV per bit
 * Beräkning av spänning sker hos Java-datorn
 */
void averageData(int& voltA, int& voltB, int& voltDiff){
	int sumA = 0;
	int sumB = 0;
	for(int i = 0; i < NUMBER_OF_SAMPLES; i++){
		sumA += analogRead(analogPinA);
		sumB += analogRead(analogPinB);
	}
	voltA = (sumA/NUMBER_OF_SAMPLES);
	voltB = (sumB/NUMBER_OF_SAMPLES);
	voltDiff = voltA - voltB;
}

/*
 * Skicka obalansvärdet från A/D-omvandlarna i form av antal bitar obalans.
 * Varje bit motsvarar 5/1023 = 0.004888 V
 * I GUI indikeras att bryggan är balanstrimmad.
 */
void zeroAdjustAlert(int voltageDiff){
	Serial.println(voltageDiff);
}

void ntcMeasurement(){
	ohm = 500;
	setCelcius(24);
	int temp = getCelcius();
	digitalWrite(LED_BUILTIN, HIGH);     	 				// visuell indikering
	Serial.write("START");
	Serial.write("\n");
	while (getCelcius() < 101) {
		Serial.print(getCelcius());
		Serial.write("  ");
		Serial.print(ohm);
		Serial.write('\n');
		delay(800);
		setCelcius(++temp);
		ohm = -5.9 * getCelcius() + 635;
		if (Serial.available() > 0){      					// kommando sänt?
			if(Serial.read() == 100){     					// 100 avbryter while-loop
				setCelcius(101);
			}
		}
	}
}

void setCelcius(int temp){
	celcius = temp;
}

int getCelcius(){
	return celcius;
}

Kod: Markera allt

import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Scanner;
import org.eclipse.swt.widgets.Display;

public class Test_1 implements Runnable {

	private DataOutputStream javaToArduinoOut = null;			//write primitive Java datatypes to an output stream
	private Scanner arduinoScanIn = null;						// produces values scanned from the specified input stream
	private String data = null;
	private Display display = null;
	private MinusZeroPlusMeter minusZeroPlusMeter = null;
	private double vMilliVolt;

	public Test_1(Display display, MinusZeroPlusMeter minusZeroPlusMeter) {
		this.display = display;
		this.minusZeroPlusMeter = minusZeroPlusMeter;
	}

	@Override
	public void run() {
		ntcBridgeZeroAdjust();
	}
	/*
	 * 	
	 */
	private void ntcBridgeZeroAdjust() {
		javaToArduinoOut = new DataOutputStream(Test.getSerialPort().getOutputStream());
		arduinoScanIn = new Scanner(Test.getSerialPort().getInputStream());
		try {
			javaToArduinoOut.writeByte(NTC.STARTZEROADJUST);	// startsignal för nolltrimma brygga i Arduinos meny
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		
		System.out.println(arduinoScanIn.findInLine("ZERO"));	// Efter texten ZERO skickas ADC-data
		arduinoScanIn.nextLine();
		
		while(true) {											// stanna kvar i nolltrim-läge tills avbrott kommer	
			try {
				Thread.sleep(20);								// måste anpassas till delay i loopen till bridgeZeroAdjust() i Arduinokoden 
			} catch (InterruptedException e) {					// fånga ett trådavbrott
				try {
					javaToArduinoOut.writeByte(200);  			// 200 är avsluta-signal för Arduinos nolltrim-funktion
					while(arduinoScanIn.hasNextLine()) {		// om arduino skickar extra
						arduinoScanIn.nextLine();				// strängar så ta inte med dessa
					}
					break;
				} catch (IOException e1) {
					e1.printStackTrace();
				}			
			}
			data = arduinoScanIn.nextLine();					// läs in data som zeroAdjustAlert-funktionen hos
			vMilliVolt = (double) Math.round(4.8888 * Double.parseDouble(data));				
			//	0 + 244 = 244 , 50*4.8888 + 244 = 488, -50*4.8888 + 244 = 0
			// progress bars är 488 steg långa vilket ger indikation mellan +/-50 mV 
			display.asyncExec (new Runnable () {			
				public void run () {
					NTC.setVdiffLabelText(vMilliVolt + " mV");
					minusZeroPlusMeter.setSelectionValue((int) Math.round(vMilliVolt*4.889+244));
				}
			});

		}
		arduinoScanIn.close();									// avsluta skannern
		try {
			javaToArduinoOut.close();							//avsluta data output stream
		} catch (IOException e) {
			e.printStackTrace();
		}						
		System.out.println("End from ntcBridgeZeroAdjust " + this.toString() + "!");
	}

	public String toString() {
		return "Test 1";
	}
}

Kod: Markera allt

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.ProgressBar;

public class MinusZeroPlusMeter implements Runnable {
	private final int PROGRESSBARMAXIMUM = 488;
	private ProgressBar pgA;
	private ProgressBar pgB;
	private Display display = null;
	private int selection;
	
	public MinusZeroPlusMeter(Display display) {
		this.display = display;
		pgA = NTC.getProgressBarA();
		pgB = NTC.getProgressBarB();
		pgA.setMaximum(PROGRESSBARMAXIMUM);
		pgB.setMaximum(PROGRESSBARMAXIMUM);
		pgA.setSelection(0);
		pgB.setSelection(0);
		this.selection = 0;
		this.setSelectionValue(244);
	}

	@Override
	public void run() {
		work();
		display.asyncExec (new Runnable () {			
			public void run () {
				pgA.setSelection(getSelectionValue());
				pgB.setSelection(PROGRESSBARMAXIMUM-getSelectionValue());
			}
		});
	}

	private void work() {	   
		while(true) {
			display.asyncExec (new Runnable () {			
				public void run () {
					pgA.setSelection(getSelectionValue());
					pgB.setSelection(PROGRESSBARMAXIMUM-getSelectionValue());
				}
			});				
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				break;
			}
		}
		System.out.println("End from Utskrift "+ this.toString() + "!");
	}
	public void setSelectionValue(int v) {
		this.selection = v;
	}
	private int getSelectionValue() {
		return this.selection;
	}
	public String toString() {
		return "MinusZeroPlusMeter";
	}
}
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Lärde mig lite ny teknik i C, inga stora saker men ändå.

När jag ska kalibrera bryggans kurva efter att ha nolltrimmat den så ska jag ansluta
2 stycken kända motstånd och funktionen som mäter spänningen ser likadan ut för
dessa två steg så alltså kan samma funktion nyttjas.

Enda skillnaden är att jag skickar kvittens till Java-programmet om att mätningen ska börja
och det utförs med en textsträng som id. Därför ska jag skicka med "RA" resp. "RB" som argument.
Jag använder pekare som dessutom kan göras tydligare med hjälp av typedef.

Att använda sig av kvittens från Arduino på skickade menyval visar sig fungera väldigt bra då
jag lägger Java-programmet i en liten loop som inväntar att rätt kvittens fås och först därefter
går vidare med övriga uppgifter.

Kod: Markera allt

#include <Arduino.h>

//Koden efterliknar en datainsamling av temperatur och NTC-motstånd
//Javaprogrammet har testats och utvecklats mot denna programkörning

// ****************************************************
//  Variabler och konstanter för kalibrering av brygga
// ****************************************************
int analogPinA = A0;                  			// bryggans anslutning A
int analogPinB = A1;                  			// bryggans anslutning B
int celcius;
int inByte = 0;
const int NUMBER_OF_SAMPLES = 100;            	// medelvärdesbilda AD-omvandla många gånger
const unsigned long BAUDRATE = 19200;

typedef char* CharPointer;
CharPointer Ra = "RA";							// samma funktion används för att kalibrera med
CharPointer Rb = "RB";							// RA och RB, bara olika id-för java-datorn

// ****************************************************
// 0 är startsignal för datainsamling i Arduinos meny
// 1 är startsignal för nollkalibrering av brygga i Arduinos meny
// 2 är startsignal för datainsamling i Arduinos meny
// 3 är startsignal för datainsamling i Arduinos meny
// 4 är Exit i Arduinos meny Serial().end;
// WHILE_LOOP_BREAK abryter while-loop i respektive mätloop

const int COLLECT_DATA = 0;
const int ZERO_ADJUST = 1;
const int CALIBRATE_RA = 2;
const int CALIBRATE_RB = 3;
const int EXIT = 4;
const int WHILE_LOOP_BREAK = 255;


// Funktionsdeklarationer
// ****************************************************
void rRefAdjust(CharPointer);
void bridgeZeroAdjust();
void averageData(double&, double&, double&);
void adjustAlert(double);
void ntcMeasurement();
int avrunda(double);
void setCelcius(int);
int getCelcius();

void setup() {
	Serial.begin(BAUDRATE);
	setCelcius(0);
	pinMode(LED_BUILTIN, OUTPUT);
	digitalWrite(LED_BUILTIN, LOW);     		// används för att testa programmet
	while (!Serial) {
		; 										// wait for serial port to connect. Needed for native USB
	}
}

// En loop med meny. Data skickas från JAVA-datorn och olika saker utförs.
// Inga av de funktioner som väljs att exekveras körs som trådar på Arduino
// så för att menysystems-loopen ska kunna hantera nästa kommando måste
// den funktion som pågår först avslutas, innan dess case-break; tillåter
// fler menyval. I GUI så kan inte fler menyval utföras förrens det pågående
// avslutats, undantag gäller EXIT för programavslut.
void loop()
{
	if (Serial.available() > 0)
	{
		inByte = Serial.read();
		switch (inByte){
		case COLLECT_DATA:                 		 // en NTC-mätning är begärd
			digitalWrite(LED_BUILTIN, HIGH);
			ntcMeasurement();         			 // funktion med while-loop, tar en stund
			break;               				 // först nu kan nya menyval utvärderas
		case ZERO_ADJUST:
			digitalWrite(LED_BUILTIN, HIGH);
			bridgeZeroAdjust();        			 // en loop som hela tiden indikerar om bryggan är nolltrimmad eller ej
			break;               		 		 // fortsätt i meny-loop när bridgeZeroAdjust() har avslutats
		case CALIBRATE_RA:
			digitalWrite(LED_BUILTIN, HIGH);
			rRefAdjust(Ra);						 // en loop som hela tiden indikerar spänningen från bryggan
			break;								 // med kalibreringsmotståndet Ra anslutet
		case CALIBRATE_RB:
			digitalWrite(LED_BUILTIN, HIGH);
			rRefAdjust(Rb);
			break;
		case EXIT:								  // Avsluta. Kvittera till Java-datorn och Stäng serieporten
			digitalWrite(LED_BUILTIN, HIGH);
			Serial.write("EXIT FROM ARDUINO");	  // Java-datorn skannar data från Arduino mha
			Serial.write("\n");					  // java.util.Scanner.Scanner(InputStream source)
			Serial.end();			  			  // nedkoppling av seriekommunikation/com-port
			break;
		default:
			digitalWrite(LED_BUILTIN, LOW);
		}
	}
	delay(100);
	digitalWrite(LED_BUILTIN, HIGH);              // visuell indikering att Arduino är aktiv utanför menyloopen
	delay(100);
	digitalWrite(LED_BUILTIN, LOW);
}
/*
 * Tar hand om  A/D-omvandlingar från två ingångar.
 * De insamlade värdena från respektive ingång är medelvärdesbildade
 * och de två ingångarnas differens-spänning skickas till Java-datorn.
 * Upplösningen är 5/1023 = 4.888 mV per bit. Differensspänningen
 * levereras som ett avrundat heltal motsvarandes antal bitar (0 till 1023).
 * Funktionen används för att ta fram ekvationen för en noll-
 * trimmad brygga mha två fasta och kända resistanser, RA och RB.
 * Loopen avbryts manuellt från GUI med tryck på en knapp.
 */
void rRefAdjust(CharPointer c){
	bool breakFlag = true;
	double averageVoltA;
	double averageVoltB;
	double vDiff;
	Serial.write(c);									// Java-datorn skannar data från Arduino mha
	Serial.write("\n");									// java.util.Scanner.Scanner(InputStream source)
	while(breakFlag){									// Den inväntar texten RA eller RB innan data börjar
		averageVoltA = 0;								// samlas in
		averageVoltB = 0;
		vDiff = 0;
		averageData(averageVoltA, averageVoltB, vDiff);  // mät obalansen medelvärdesbilda en aning
		adjustAlert(vDiff);                     	 	 // skicka obalansspänning till Java-dator
		if (Serial.available() > 0){                     // kommando sänt? Avbryt balanstrimmning av brygga?
			if(Serial.read() == WHILE_LOOP_BREAK){       // 200 avbryter while-loop
				breakFlag = false;
			}
		}
	}
}
/*
 * En loop som mäter obalansen i NTC-mätbryggan.
 * Upplösningen är 5/1024 = 4.883 mV per bit
 * Två spänningar från två ADC-ingångar mäts och medelvärdesbildas.
 * Sedan tas differensen av dessa spänningar och utifrån denna differens
 * avgörs om bryggan anses vara i balans/nolltrimmad. Arduino skickar
 * differensen till Java-datorn i form av antalet bitar (0 till 1023)
 * Ex. 2 bitar ger 2*4.8876 = 9.78mV
 *
 * Loopen avbryts manuellt från GUI med tryck på en knapp.
 */
void bridgeZeroAdjust(){
	bool breakFlag = true;
	double averageVoltA;
	double averageVoltB;
	double vDiff;										// Java-datorn skannar data från Arduino mha
	Serial.write("ZERO");								// java.util.Scanner.Scanner(InputStream source)
	Serial.write("\n");									// Den inväntar texten ZERO innan data börjar
	while(breakFlag){									// samlas in
		averageVoltA = 0;
		averageVoltB = 0;
		vDiff = 0;
		averageData(averageVoltA, averageVoltB, vDiff);  // mät obalansen medelvärdesbilda en aning
		adjustAlert(vDiff);                     	 	 // skicka obalansspänning till Java-dator
		if (Serial.available() > 0){                     // kommando sänt? Avbryt balanstrimmning av brygga?
			if(Serial.read() == WHILE_LOOP_BREAK){       // avbryter while-loop ( < 256 pga byte)
				breakFlag = false;
			}
		}
	}
}

/*
 * Argumenten voltA, voltB och voltDiff är call by reference
 * Två spänningar från två ADC-ingångar mäts och medelvärdesbildas.
 * Skillnaden mellan dessa spänningar är obalansspänningen i bryggan.
 * Upplösningen är 5/1023 = 4.89 mV per bit
 * Beräkning av spänning sker i Java-datorn
 */
void averageData(double& voltA, double& voltB, double& voltDiff){
	double sumA = 0;
	double sumB = 0;
	for(int i = 0; i < NUMBER_OF_SAMPLES; i++){
		sumA += analogRead(analogPinA);					// A/D-omv. tar 100us
		delayMicroseconds(25);
		sumB += analogRead(analogPinB);
		delayMicroseconds(25);
	}
	voltA = (sumA/NUMBER_OF_SAMPLES);
	voltB = (sumB/NUMBER_OF_SAMPLES);
	voltDiff = voltA - voltB;
}

/*
 * Skicka obalansvärdet från A/D-omvandlarna i form av antal bitar obalans.
 * Varje bit motsvarar 5/1023 = 0.004888 V
 * I GUI indikeras att bryggan är balanstrimmad.
 */
void adjustAlert(double voltageDiff){
	Serial.println(avrunda(voltageDiff));
}

void ntcMeasurement(){
	int ohm = 500;
	setCelcius(24);
	int temp = getCelcius();
	Serial.write("START");
	Serial.write("\n");
	while (getCelcius() < 101) {
		Serial.print(getCelcius());
		Serial.write(" ");
		Serial.print(ohm);
		Serial.write("\n");
		delay(800);
		setCelcius(++temp);
		ohm = -5.9 * getCelcius() + 635;
		if (Serial.available() > 0){      					// kommando sänt?
			if(Serial.read() == WHILE_LOOP_BREAK){     		// avbryter while-loop
				setCelcius(101);
			}
		}
	}
}
/*
 * Avrunda en double till ett heltal
 */
int avrunda(double number){
	return static_cast<int>(floor(number + 0.5));
}
void setCelcius(int temp){
	celcius = temp;
}

int getCelcius(){
	return celcius;
}


Exempelvis när jag vill mäta med RA ansluten så körs koden nedan.
För det mesta visar det sig att loopen som väntar på kvittens inte
är nödvändig. Jag tror den eventuellt kan uteslutas men ibland har
utströmmen andra tecken kvar så jag får testa detta lite mer.

Sedan har jag gjort så att Scanner och DataOutputStream öppnas
när serieporten öppnats och sedan får de vara öppna tills hela programmet
avslutas. Det verka fungera betydligt bättre än att hålla på att stänga och öppna för varje
nytt uppdrag.

Kod: Markera allt

import java.io.IOException;
import java.util.NoSuchElementException;

public class Test_2 implements Runnable {
	private String data;
	private int vMilliVolt;
	private int value;
	
	public Test_2() {

	}

	@Override
	public void run() {
		NTC.getThreadControllerThread()[5] = new Thread (NTC.getThredController()[5]);				
		try {
			NTC.getThreadControllerThread()[5].start();					 // MinusZeroPlusMeter
		} catch (IllegalThreadStateException itse) {
			System.out.println("IllegalThreadStateException");
		}
		ntcBridgeAdjustRA();
		try {
			NTC.getThreadControllerThread()[5].interrupt();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
		System.out.println("End from  " + this.toString() + "!");
	}
	
	private void ntcBridgeAdjustRA() {					
		try {
			NTC.getJavaToArduinoOut().writeByte(NTC.STARTREFA);	// startsignal för kalibrera brygga med referens RA
		} catch (IOException e1) {								// i Arduinos meny
			e1.printStackTrace();
		}
		int i = 0;
		try {
			data = NTC.getArduinoScanIn().nextLine();
		} catch(NoSuchElementException e) { }
		while(!data.equals(NTC.ARDUINOCALIBRATE_RA)) {			// Efter texten skickas ADC-data
			try {
				data = NTC.getArduinoScanIn().nextLine();
			} catch(NoSuchElementException e) { }
			i++;
		}			
		System.out.println("data = " + data + " i = " + i);							
			
		while(true) {											// stanna kvar i kalibrerings-läge								
			try {
				Thread.sleep(2);								
			} catch (InterruptedException e) {					// fånga ett trådavbrott
				try {
					NTC.getJavaToArduinoOut().writeByte(NTC.WHILELOOPEXIT);  // avsluta-signal för Arduinos mätloop
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				break;											// hoppa ur while-loop och avsluta
			}
			try {
				data = NTC.getArduinoScanIn().nextLine();		// läs in data motsvarande bryggans
			} catch(NoSuchElementException e) { }
		
			try {												// obalansspänning för RrefA
				value = Integer.parseInt(data);					// data är a/d-omvandlarens bitvärde som ett heltal
			} catch(java.lang.NumberFormatException nfe) {		// levererat som en textsträng
				System.out.println("NumberFormatException in Test 2");
			}
							
			vMilliVolt = (int) Math.round(4.8828 * value); 	// 5V/1023 = 4.888 mV/bit
			//	0 + 244 = 244 , 50*4.888 + 244 = 488, -50*4.888 + 244 = 0
			// progress bars är 488 steg långa vilket ger indikation mellan +/-50 mV 
			NTC.getDisplay().asyncExec (new Runnable () {			
				public void run () {
					NTC.getLabelVdiff().setText(vMilliVolt + " mV" + " data (0-1023) = " + data);
					NTC.getMinusZeroPlusMeter().setSelectionValue((int) Math.round(vMilliVolt*4.8828+244));
				}
			});
		};		
	}
	public String toString() {
		return "Kalibrera med RrefA";
	}
}
Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

När bryggan är nolltrimmad och de två spänningarna VA och VB är uppmätta med
två kända resistanser RA och RB så ska den räta linjen beräknas för att få fram
formeln på formen y = kx + m

Jag får se senare om jag lägger till en tredje mätpunkt mitt på kurvan. Då får
jag approximera linjen med ett polynom. Det beror på om jag vill ha bättre resultat eller ej.

När jag väl har ekvationen så kan jag låta Arduino starta uppvärmning av blocket och läsa in
spänningen y och beräkna NTC-motståndet.

Jag har inte riktigt bestämt ännu hur jag ska mäta temperaturen. Jag hade ju tänkt att mäta
till minst 150 grader och då finns några fler alternativ än RTD-sensorer att välja på men RTD
verkar ju vara något som ger noggrannast värde.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Mindmapper
Inlägg: 6389
Blev medlem: 31 augusti 2006, 16:42:43
Ort: Jamtland

Re: Mätapplikation med Arduino och Java

Inlägg av Mindmapper »

Definitivt ska du använda en RTD.
En thermistor typ NTC har en väldigt olinjär kurva. Definitivt ingen räta linjen.

En RTD däremot har en bra linjäritet.
Bra teori om tempmätning.
https://pentronic.se/start/temperaturgi ... ivare.aspx
Även om PT100 är industristandard, så kan PT1000 vara ett alternativ.
Du kan använda tabellerna för PT100 och multiplicera resistansvärdet med 10.
Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

NTC går ju använda bara man mätt upp den noga, precis vad jag ska
använda bygget till. Men det är ju svårt innan man vet NTC-kurvan.
PTC går ju också bra att använda men samma visa där.
Användarvisningsbild
4kTRB
Inlägg: 18289
Blev medlem: 16 augusti 2009, 19:04:48

Re: Mätapplikation med Arduino och Java

Inlägg av 4kTRB »

Testade med att ansluta ett 553 ohms motstånd och nolltrimmade.
Sedan ett 389 ohms för att få spänningen VA.
Och sist ett 47 ohms för spänningen VB.
Resultatet blir si så där.

VA = 0.472972
VB = 1.7602360000000001
RA = 389.0
RB = 47.0
k = -0.003763929824561404
m = 1.937140701754386

Räknade på vilka värden det skulle mäta vid 0V och 1.54 (vilket var det jag fick med ett 100 ohms)
NTC 0V = 514.7
NTC 1.54V = 105.5

515 är en bit ifrån 553 medans det stämmer bättre för 100 ohm.
Avgörande för felet är nog trots allt upplösningen på 4.9mV per steg.
10-bitars A/D är nog inte tillräckligt för att få bättre resultat än så här.

Koden som körs för att ta fram ekvationen...

Kod: Markera allt


public class LinearEquation {
	
	private double va;
	private double vb;
	private double ra;
	private double rb;
	private double k;
	private double m;

	public LinearEquation() {
		va = vb = ra = rb = k = m = 0;
	}
	
	public void setVa(double value) {
		this.va = value;
	}
	public double getVa() {
		return this.va;
	}
	public void setVb(double value) {
		this.vb = value;
	}
	public double getVb() {
		return this.vb;
	}
	public void setRa(int value) {
		this.ra = (double) value;
	}
	public double getRa() {
		return this.ra;
	}
	public void setRb(int value) {
		this.rb = (double) value;
	}
	public double getRb() {
		return this.rb;
	}
	public void calculate_k() {		
		this.k = (this.vb-this.va)/(this.rb-this.ra);				
	}
	public double get_k() {
		return this.k;
	}
	public void calculate_m() {
		this.m = this.vb-this.k*this.rb;
	}
	public double get_m() {
		return this.m;
	}
	public double calculateNTCresistance(double voltage){		
		return (voltage - this.m) / this.k;
	}	
}
Skriv svar