Winkelmessung

Die Winkelmessung befasst sich mit der Richtungsorientierung der Solarzelle bezüglich der vorhandenen Spannung. Die Solarzelle kann sich mithilfe von 2 Achsen in Horizontale und Vertikale Richtung drehen. Die Horizontale hat einen Gesamtdrehwinkel von 360 Grad und die Vertikale einen von 90 Grad. Den Winkel bestimmen wir über die Drehzahl, die wir von der Motorgruppe übergeben bekommen. Dieser wird in Form von Pulsen an uns weitergegeben. Dabei ist ein Puls eine 1/2 Umdrehung. Um die Drehzahl nun bestimmen zu können, müssen die einzelnen Pulse gezählt werden. Dies geschieht mit einem 64 Bit Zähler der in unserem Code integriert wird. Da sich die Solarzelle sowohl nach links als auch nach rechts drehen soll, muss uns die Drehrichtung bekannt sein, um den Winkel überhaupt berechnen zu können. Die Drehrichtung liegt als 2.5 V Referenzspannung auf dem Bus. Es muss nach jedem Puls überprüft werden, ob die Drehrichtung kleiner als die 2.5 V Referenzspannung oder größer ist. Je nachdem, wenn es kleiner als 2.5 V ist, findet eine Linksdrehung statt und der Zähler wird incrementiert, sonst findet eine Rechtsdrehung der Solarzelle statt und der Zähler wird decrementiert. Bei genau 2.5 V soll sich die Solarzelle nicht drehen. Daher ist es von Vorteil, den Zähler mittig zu initialisieren. Um den Vergleich im Mikrocontroller realisieren zu können, wird als Bauteil ein Analog Comparator benötigt. Dieser gibt ein High Signal aus, sobald die Drehrichtung unter den 2.5 V Referenzspannung ist. Nach der Ermittelung dieser Werte wird mit folgender Formel die Drehzahl berechnet:

Formel 1

wobei n den zuvor berechnete Drehzahl beschreibt.
Die an uns gestellte Forderung der Lichtsensorgruppe ist, dass folgende Funktionalitäten von uns realisiert werden, damit die Solarzelle zu seiner Standardposition zurückkehren kann, wenn die Solarzelle im Nachtmodus ist.
Es sind 4 Signale vorhanden:\\
Signal 1 = links, Signal 2 = rechts,\\
Signal 3 = unten, Signal 4 = oben

Folgendes soll nun umgesetzt werden:\\
links > rechts => Linksdrehung gewünscht, um Standardposition zu erreichen\\
links = rechts => keine Drehung gewünscht, Standardposition erreicht\\
links < rechts => Rechtsdrehung gewünscht, um Standardposition zu erreichen\\

Um dies zu realisieren haben wir uns folgendes überlegt:
Jeweils für Horizontale und Vertikale Winkel werden von uns 2 Signale erwartet. Der eine Signal soll den Ursprungswinkel 0 Grad darstellen. Wir legen fest, dass der Ursprungswinkel genau die Spannung 2,5V besitzt. Der zweite Signal soll den von uns berechneten Winkel widerspiegeln. Dazu legen wir fest, dass für den Horizontalen Winkel zwischen [0V – 2,5V] der Bereich von 0 Grad bis -180 Grad dargestellt wird und zwischen [2,5V – 5V] der Bereich von 0 Grad bis 180 Grad.

Um den genauen Winkel nun bestimmen und als Spannung zurückgeben zu können, wurde folgende mathematische Funktion hergeleitet:

Formel 2Als Eingang wird der zuvor berechnete Winkel verwendet. Der Winkel wird mit der Spannung pro 1 Grad multipliziert und ein Offset von 2,5V dazu addiert.
So können wir für jeden Winkel eine Spannung zuordnen und diese in Form von Signalen an die Lichtsensorik-Gruppe weiterleiten. Jedoch werden von uns Analoge Signale erwartet. Daher wird zusätzlich noch ein weiteres Bauteil benötigt, ein DA-Wandler. Deren Aufgabe ist es, den zuvor berechneten Wert in ein analoges Signal umzuwandeln.

Schaltplan

Da wir nur wenige Bauteile benötigten, haben wir eine Leiterplatte mit der Display-Kleingruppe geteilt. Im folgenden die einzelnen Teilschaltungen von den Bauteilen:

2-1_comparator

Um die Bauteile vor Überspannung zu schützen, haben wir als Spannungsbegrenzer vor dem Analog Comparator eine Z-Diode mit einem Vorwiderstand von 100 Ohm geschaltet. So wird gewährleistet, dass die Spannung den Wert von 5 Volt nicht überschreitet.

2-1_DAwandlerMit dem DA-Wandler wird über die SPI-Interface kommuniziert.

Programmierung

Winkelmessung Hilfsfunktion:

/*
* GccApplication1.c
*
* Created: 08.12.2015 15:47:01
* Author: azmi
*/
#include <avr/io.h>
#include <stdint.h> // uint64_t

void init_winkel()
{
DDRB |= (1<<PB1);//LDAC als output
/*PD2,PD3,PB3,PB2 als input*/
}

int getDir()//Comparator: wenn direction1 < 2.5V(linksdrehung), dann condition=1
{
int condition = ACSR & 0x20;
return condition;
}

void SPI_MasterInit(void)
{
DDRB = (1<<PB5)|(1<<PB7);//Set MOSI and SCK output, all others input
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);//Enable SPI, Master, set clock rate fck/16
}

void SPI_MasterTransmit(char cData)
{
SPDR = cData;//Start transmission
while(!(SPSR & (1<<SPIF))){}//Wait for transmission complete
}

int aufrunden(double z)
{
double z_diff;
z_diff=z-(int)z;
if(z_diff>0)
{
int neu=(int)z+1;
return neu;
}
else
{
return (int)z;
}
}

double getPhi(void)
{
double cycles,phi_V,phi;
double alpha = 0.125;
uint64_t zaehler,zaehler_start;
zaehler=((2^64)-1)/2;//Zaehlt die Drehpulse, mittig initialisiert
zaehler_start=((2^64)-1)/2;//Zaehler

if(getDir()>0)//wenn Linksdrehung, Zaehler incrementieren
{
zaehler++;
}
else//wenn Rechtsdrehung, Zaehler decrementieren
{
zaehler–;
}

cycles=0.5*alpha*(zaehler-zaehler_start);//Drehzahl
phi = 360*cycles;//Winkel
phi_V = (2.5/180)*phi+2.5;//Rad –> Volt
double V_out = phi_V*204.6;
int V = aufrunden(V_out);
return V;

Winkemessung Hauptfunktion:

/*
* GccApplication2.c
*
* Created: 12.01.2016 14:19:32
*  Author: azmi
*/

#define F_CPU 1000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include „winkel.h“

int main(void)
{
sei();// Global Interrupt enable
GICR |=(1<<INT0);// enable INT0 in General Interrupt Control Register
init_winkel();
SPI_MasterInit();
DDRB|=1;
while(1)
{
PORTB |= 1;
_delay_ms(1000);
PORTB &= ~1;
_delay_ms(1000);
}
}

ISR(INT0_vect)
{
uint8_t spiData1,vData1,vData2;
int V=getPhi();
PORTB &= ~(1<<PB4);
spiData1 = 0x30; // ersten 8 bit versenden
vData1 = (0x3C0 & V) >> 6;
spiData1 = spiData1 | vData1;
vData2 = (0x3F & V);// letzten 8 bit versenden
SPI_MasterTransmit(spiData1);
SPI_MasterTransmit(vData2);
PORTB |= (1<<PB4);
}