-         

Ergebnis 1 bis 8 von 8

Thema: RP6Control M32: Rechteck-Generator

  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.791

    RP6Control M32: Rechteck-Generator

    Anzeige

    Hallo RP6-Fans,

    manchmal braucht man eine bestimmte Frequenz (symmetrisches Rechteck-Signal, keine PWM), um ein eigenes Programm auf einem anderen uC zu testen oder um einen uC ohne Quarz wieder zu beleben.

    Dieser Rechteck-Generator erzeugt Frequenzen am OC1A Pin der M32 (I/O-Stecker Pin 9 = PD5).

    Der Generator startet mit 1kHz Rechteck. Man kann dann über das Terminal eine neue Frequenz im Bereich 0,12 bis 4000000 Hz eingeben.

    Diese Frequenz wird möglichst genau eingestellt (Timer1 im CTC Modus) und an OC1A ausgegeben. Die Abweichung der erzeugten von der gewünschten Frequenz gibt das Programm in Promille am Terminal aus.

    Leider kann nicht jede Frequenz mit diesem Programm erzeugt werden!

    Viel Spaß damit!

    Dirk
    Code:
    /* 
     * ****************************************************************************
     * RP6 ROBOT SYSTEM - RP6 CONTROL M32 TESTS
     * ****************************************************************************
     * Beispiel: Rechteckgenerator
     * Autor(en): Dirk
     * ****************************************************************************
     * Beschreibung:
     *
     * Mit diesem Programm kann eine symmetrische Rechteck-Frequenz am OC1A Pin
     * der M32 (PD5, I/O-Stecker Pin 9) erzeugt werden.
     * Du kannst die gewünschte Frequenz am Terminal eingeben. Das Programm ver-
     * sucht, diese Frequenz so gut wie möglich einzustellen und gibt die
     * Ausgabe-Frequenz und die Abweichung von der gewünschten Frequenz in
     * Promille [o/oo] am Terminal aus.
     * Die gewählte Frequenz wird an OC1A ausgegeben, bis du eine neue Frequenz
     * auswählst.
     * Das Programm ist KEIN DDS, daher kann nicht jede Frequenz eingestellt
     * werden.
     *
     * Technische Daten:
     * -----------------
     *  Frequenzbereich:		0,12 [Hz] ... 4,0 [MHz]
     *  Start-Frequenz:			1000 [Hz]
     *  Generator Stop:			Gib 0 ein
     *  Generator Start:		Gib eine neue Frequenz ein
     *
     * ############################################################################
     * Der Roboter bewegt sich NICHT in diesem Beispiel! Du kannst ihn einfach auf
     * einen Tisch neben deinen PC stellen und solltest ihn mit dem PC über das
     * USB-Interface verbinden!
     * ############################################################################
     * ****************************************************************************
     */
    
    /*****************************************************************************/
    // Einzufügende Dateien:
    
    #include "RP6ControlLib.h"
    
    #include "RP6uart_2.h"
    
    /*****************************************************************************/
    // Definitionen:
    
    #define INFO							// Zeige zusätzliche Informationen
    
    /*****************************************************************************/
    // Variablen:
    
    double freq_target;						// Gewünschte Frequenz
    double freq_actual;						// Aktuelle Frequenz
    double deviation;						// Abweichung [Promille]
    const uint16_t prescalers[5] = {1, 8, 64, 256, 1024}; // Alle Vorteiler
    uint8_t psindex;						// Vorteiler Index
    uint16_t prescaler;						// Aktueller Vorteiler
    uint16_t topvalue;						// Aktueller OCR1A Spitzenwert
    
    /*****************************************************************************/
    // Funktionen:
    
    /**
     * SETZE NEUE FREQUENZ
     *
     * Ruf diese Funktion auf, wenn du eine neue Frequenz einstellen willst.
     *
     */
    void setNewFrequency(double f_target)
    {uint32_t topvalue32 = 0; double temp;
    	if (f_target == 0) {
    		TCCR1A &= ~(1 << COM1A0);		// OC1A nicht verbunden 
    		PORTD &= ~IO_PD5;				//  und PD5 auf Nullpegel
    		topvalue = 0;
    		return;
    	}
    	else {
    		temp = (double) F_CPU / 4;
    		if (f_target > temp) f_target = temp;
    		temp = (double) F_CPU / (2 * 1024 * 65535);
    		if (f_target < temp) f_target = temp;
    		TCCR1A |= (1 << COM1A0);		// OC1A verbunden
    	}
    	for (psindex = 0; psindex < 5; psindex++) {
    		prescaler = prescalers[psindex];
    		temp = (double) F_CPU / (2 * prescaler * f_target) - 1;
    		topvalue32 = temp + 0.5;		// Runde zum Integer-Wert
    		if (topvalue32 < 65535) break;
    	}
    	topvalue = (uint16_t) topvalue32;
    	cli();
    	switch (prescaler) {
    		case 1 :
    			TCCR1B =  (0 << WGM13)		// Vorteiler 1
    					| (1 << WGM12) 
    					| (0 << CS12) 
    					| (0 << CS11) 
    					| (1 << CS10);
    			break;
    		case 8 :
    			TCCR1B =  (0 << WGM13)		// Vorteiler 8
    					| (1 << WGM12) 
    					| (0 << CS12) 
    					| (1 << CS11) 
    					| (0 << CS10);
    			break;
    		case 64 :
    			TCCR1B =  (0 << WGM13)		// Vorteiler 64
    					| (1 << WGM12) 
    					| (0 << CS12) 
    					| (1 << CS11) 
    					| (1 << CS10);
    			break;
    		case 256 :
    			TCCR1B =  (0 << WGM13)		// Vorteiler 256
    					| (1 << WGM12) 
    					| (1 << CS12) 
    					| (0 << CS11) 
    					| (0 << CS10);
    			break;
    		case 1024 :
    			TCCR1B =  (0 << WGM13)		// Vorteiler 1024
    					| (1 << WGM12) 
    					| (1 << CS12) 
    					| (0 << CS11) 
    					| (1 << CS10);
    	}
    	OCR1A = topvalue;
    	sei();
    }
    
    /*****************************************************************************/
    // Haupt Funktion - Das Programm beginnt hier:
    
    int main(void)
    {uint8_t i;
    	initRP6Control();
    
    	initLCD();
    
    	showScreenLCD("Rechteck-Gener. ", "  Version 1.00  ");
    
    	writeString_P("\n\n   _______________________\n");
    	writeString_P("   \\| RP6  ROBOT SYSTEM |/\n");
    	writeString_P("    \\_-_-_-_-_-_-_-_-_-_/\n\n");
    
    	writeString_P("################\n");
    	writeString_P("<<RP6  Control>>\n");
    	writeString_P("Rechteck-Gener. \n");
    	writeString_P("  Version 1.00  \n");
    	writeString_P("################\n\n");
    	mSleep(2500);
    
    	setLEDs(0b111111);
    	mSleep(500);
    	setLEDs(0b000000);
    
    	// Initialisiere den M32 OC1A Pin (PD5) als Ausgang: 
    	DDRD |= IO_PD5;
    
    	// Initialisiere den M32 Timer1 "Lösche Timer
    	//  bei Vergleichs-Übereinstimmung" (CTC) Modus:
    	cli();
    	// Timer 1:
    	// Kein Vorteiler, Modus 4 (CTC, Spitzenwert OCR1A),
    	// schalte OC1A um bei Vergleichs-Übereinstimmung.
    	TCCR1A =  (0 << COM1A1) 
    			| (1 << COM1A0) 
    			| (0 << FOC1A) 
    			| (0 << WGM11) 
    			| (0 << WGM10);
    	TCCR1B =  (0 << WGM13) 
    			| (1 << WGM12) 
    			| (0 << CS12) 
    			| (0 << CS11) 
    			| (1 << CS10);
    	OCR1A = F_CPU / 2000 - 1;			// 1 kHz beim Start
    	// Schalte Ausgabe-Vergleichs-Übereinstimmungs A Interrupts aus:
    	TIMSK &= ~(1 << OCIE1A);
    	sei();
    
    	while(true)
    	{
    		writeString_P("\n\n\n\n\n\n\n\n");
    		writeString_P("\n|============================|");
    		writeString_P("\n| Rechteck - Generator  V1.0 |");
    		writeString_P("\n|============================|");
    		writeString_P("\n| Zielfrequenz [Hz] eingeben |\n");
    		enterString();
    		i = 0;
    		while (receiveBuffer[i]) {		// Ersetze ',' durch '.'
    			if (receiveBuffer[i] == ',') receiveBuffer[i] = '.';
    			i++;
    		}
    		writeString_P("|============================|\n");
    
    		freq_target = atof(&receiveBuffer[0]);
    		writeString_P("| F-Ziel    ");
    		writeDouble(freq_target, 11, 3);
    		writeString_P(" [Hz]");
    		writeString_P("\n|============================|");
    
    		setNewFrequency(freq_target);
    		if (topvalue) {
    #ifdef INFO
    			writeString_P("\n| Neue OCR1A Spitze ");
    			writeLong(topvalue, DEC);
    			writeString_P("\n| Neuer Vorteiler   ");
    			writeLong(prescaler, DEC);
    			writeString_P("\n|============================|");
    #endif
    			freq_actual = (double) 2 * prescaler * (1 + topvalue);
    			freq_actual = (double) F_CPU / freq_actual;
    			writeString_P("\n| F-Aktuell ");
    			writeDouble(freq_actual, 11, 3);
    			writeString_P(" [Hz]");
    			writeString_P("\n|============================|");
    #ifdef INFO
    			deviation = (freq_actual - freq_target) / freq_target * 1000;
    			writeString_P("\n| Abweichung ");
    			writeDouble(deviation, 7, 3);
    			writeString_P(" [o/oo]");
    			writeString_P("\n|============================|");
    #else
    			writeString_P("\n\n\n\n\n");
    #endif
    		}
    		else {
    			writeString_P("\n| Generator ist jetzt aus!!! |");
    			writeString_P("\n|============================|");
    			writeString_P("\n\n\n\n\n");
    		}
    	}
    	return 0;
    }
    
    /******************************************************************************
     * Additional info
     * ****************************************************************************
     * Changelog:
     * - v. 1.0 (initial release) 07.03.2010 by Dirk
     *
     * ****************************************************************************
     */
    
    /*****************************************************************************/

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.05.2009
    Ort
    Berlin
    Beiträge
    450
    Hi,
    ein Programmcode mit Deutschem Bemerkungen. Sollte es doch Programmierer geben die Wissen wo ihr Code gelesen wird. Da könnte sich so mancher ein Beispiel dran nehmen. Danke
    Trainmen

  3. #3
    Erfahrener Benutzer Roboter Experte Avatar von Virus
    Registriert seit
    15.09.2009
    Ort
    Duisburg
    Alter
    22
    Beiträge
    527
    danke, gute idee.

    du könntest noch die .hex posten aber sonst ists jut!
    Mit hochohmigen Grüßen
    Virus

    Es lebe der Digitalkäse !

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.791
    Hallo Leute,

    ich hatte noch die RP6uart_2 Lib vergessen. Die wird von dem Programm gebraucht und muss auch ins makefile mit:
    SRC += $(RP6_LIB_PATH)/RP6common/RP6uart_2.c
    ... eingetragen werden.

    RP6uart_2.h:
    Code:
    #ifndef RP6UART_2_H
    #define RP6UART_2_H
    #include "RP6uart.h"
    #define PRECISION 6
    #define DTOSTR_ALWAYS_SIGN 0x01
    #define DTOSTR_PLUS_SIGN 0x02
    #define DTOSTR_UPPERCASE 0x04
    char receiveBuffer[UART_RECEIVE_BUFFER_SIZE + 1];
    void writeLong(int32_t number, uint8_t base);
    void writeLongLength(int32_t number, uint8_t base, uint8_t length);
    void writeDouble(double number, uint8_t width, uint8_t prec);
    void writeDoubleExp(double number, uint8_t prec, uint8_t flags);
    uint8_t getInputLine(void);
    void enterString(void);
    #endif
    RP6uart_2.c:
    Code:
    #include "RP6uart_2.h"
    void writeLong(int32_t number, uint8_t base) {char buffer[33]; ltoa(number, &buffer[0], base); writeString(&buffer[0]);}
    void writeLongLength(int32_t number, uint8_t base, uint8_t length) {char buffer[33]; ltoa(number, &buffer[0], base); int8_t cnt = length - strlen(buffer); if(cnt > 0) {for(; cnt > 0; cnt--, writeChar('0')); writeString(&buffer[0]);} else writeStringLength(&buffer[0], length, -cnt);}
    void writeDouble(double number, uint8_t width, uint8_t prec) {char buffer[width + 1]; dtostrf(number, width, prec, &buffer[0]); writeString(&buffer[0]);}
    void writeDoubleExp(double number, uint8_t prec, uint8_t flags) {char buffer[prec + 8]; dtostre(number, &buffer[0], prec, flags); writeString(&buffer[0]);}
    uint8_t getInputLine(void) {static uint8_t buffer_pos = 0; if(getBufferLength()) {receiveBuffer[buffer_pos] = readChar(); if((receiveBuffer[buffer_pos] == '\n') || (receiveBuffer[buffer_pos] == '\r')) {receiveBuffer[buffer_pos] = '\0'; buffer_pos = 0; return 1;} else if(buffer_pos >= UART_RECEIVE_BUFFER_SIZE) {receiveBuffer[UART_RECEIVE_BUFFER_SIZE] = '\0'; buffer_pos = 0; return 2;} buffer_pos++;} return 0;}
    void enterString(void) {while(!getInputLine());}
    In dieser Lib sind einige UART-Funktionen ausgelagert.

    Gruß Dirk
    Geändert von Dirk (24.05.2014 um 13:49 Uhr) Grund: Neue Version

  5. #5
    Erfahrener Benutzer Roboter Experte Avatar von Virus
    Registriert seit
    15.09.2009
    Ort
    Duisburg
    Alter
    22
    Beiträge
    527
    die .hex und man ist das Problem los.

    auserdem braucht man für die von dir genannten Zecke den Quellcode nicht, naja geht auch so.
    Mit hochohmigen Grüßen
    Virus

    Es lebe der Digitalkäse !

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.791
    die .hex und man ist das Problem los. auserdem braucht man für die von dir genannten Zecke den Quellcode nicht,...
    Nachteil:
    Nur mit HEX lernt man NIX!

    Gruß
    Dirk

  7. #7
    Erfahrener Benutzer Roboter Experte Avatar von Virus
    Registriert seit
    15.09.2009
    Ort
    Duisburg
    Alter
    22
    Beiträge
    527
    da hast du natürlich absolut recht
    Mit hochohmigen Grüßen
    Virus

    Es lebe der Digitalkäse !

  8. #8
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    54
    Beiträge
    5.781
    Blog-Einträge
    8
    Hallo

    Nur mit HEX lernt man NIX!
    Das stimmt wohl schon im Prinzip, aber bei "manchmal braucht man eine bestimmte Frequenz" mag wohl keiner wissen, wie die erzeugt wird.

    du könntest noch die .hex posten
    Wenn du sie jetzt hast könnest du sie auch selbst posten ;)

    Und wen wirklich interessiert, wie das funktioniert, der läd sich die Hex-Datei eh nicht runter.

    Gruß

    mic

    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •