Bluecontroller (BCA8-BTM)

From XennisWiki
Jump to: navigation, search

Latest stable Version: Epsilon (tested and proven to work) on GitHub!

Das AVR C-Programm dient zum Senden und Empfangen von Textnachrichten über Bluetooth zwischen einem Mikrocontroller und einem Computer:

Microcontroller <-> UART <->    Bluetooth    <-> COM Port <-> PC

Hierfür wurde der Bluecontroller verwendet, sodass sich in unserem konkreten Fall der folgende Ablauf ergibt:

ATmega328p <-> USART0 <-> BTM-222 <->    Bluetooth    <-> Bluetooth-Gerät-Am-PC <-> COM Port <-> RS232 Terminal <-> Windows-PC

Projekt

mReS-R Modul zum Training von Rotationsbewegungen

Institut für Technische Informatik, Universität zu Lübeck:

  • Autoren: Fabi Rosenthal, Florian Thaeter, Mai Linh E. Nguyen
  • Verantwortliche: Dipl.-Ing. Patrick Weiss, Dipl.-Inf. Alexander Gabrecht

mReS - Modular Rehabilitation System

Das Bluecontroller-Projekt ist am Institut für Technische Informatik der Universität zu Lübeck im Rahmen des mReS-Projekts entstanden:

mReS ist ein modular RehabilitationsSystem zum Training der Handfunktion nach Schlaganfall. Die Modularität erlaubt ein breites Spektrum an Trainings- und Fortschrittsbewertungsmöglichkeiten bei gleichzeitiger Reduzierung der Komplexität und Kosten. Dadurch sollen die Systeme auch in kleineren Kliniken mit begrenzten finanziellen Mitteln und in der Heimrehabilitation eingesetzt werden können. Der therapeutische Ansatz beruht auf einer adaptiven, visuellen Rückmeldung hinsichtlich der motorischen Leistungen des Patienten, der auf neurowissenschaftlich bekannten Wirkmechanismen einer sogenannten verzerrten Rückmeldung basiert. (mReS)

mReS-R ist dabei ein Module zum Training von Rotationsbewegungen. Im Rahmen des Bluecontroller-Projekts soll dieses Module über Bluetooth angesteuert werden. Hierfür müssen Motorbefehle über UART an den Bluecontroller gesendet werden, damit der enthaltende Mikrocontroller diese verarbeiten kann.

Verwendete Hard- und Software

Bluecontroller (BCA8-BTM-328P-BOOT) im Betrieb

Hardware

Software (unter Windows 7)

Bluecontroller

Weitere Hilfe: Bluecontroller, BTM-222 Bluetooth-Funkmodul

Modi Command Mode und Communication mode

Das Bluetooth Modul unterscheidet zwischen den beiden Modi Command Mode und Communication mode. Im Command Mode können Einstellungen am Modul vorgenommen werden, indem man die entsprechenden AT-Befehle sendet, während im Communication Mode alle Daten an den Bluetooth Kommunikationspartner weitergesendet werden.

Wechsel zwischen den Modi

Nach einem Reset befindet sich das Modul standardmäßig im Command Mode.

Wechsel vom Command Mode in Communication Mode:

  • Geschieht automatisch, wenn erfolgreich eine Bluetooth Verbindung aufgebaut wurde

Wechsel vom Communication Mode in Command Mode:

  • Verbindung zum Kommunikationspartner abrechen
  • (oder) Escape-Sequenz senden, welche jedoch standardmäßig deaktiviert ist und erst über die Einstellung ATX1 aktiviert werden muss

Abfrage des Modus

Das Programm sollte wissen, in welchem der Modi sich das Modul aktuell befindet, da im Command mode alle Strings als Befehl interpretiert werden. Will man also eigentlich gerade Daten senden, kann dies zu ungeahnten Fehler führen. Aktiviert man die ATQ0 Option aktivieren, sende das Modul die Resul codes[1] zurück:

  • OK
  • CONNECT
  • DISCONNECT
  • ERROR

Um nun zu überprüfen, ob man sich gerade im Command Mode befindet, kann man zum Beispiel das AT Kommando schicken. Wird dies mit OK beantwortet, befindet man sich im Command Mode.

Atmel Studio

Das Atmel Studio 6 haben wir zum Programmieren und Kompilieren verwendet. Die ältere Version (Studio 4) haben wir nur dazu genutzt, dass mit Studio 6 erstellte hex-File auf den Mikrocontroller zu überspielen, da das Studio 6 nicht kompatibel mit dem verwendeten Programmer STK500 ist. In den Fuses oder sonst irgendwo, müssen generell keine extra Einstellungen vorgenommen werden.

Unter Programming Mode and Target Settings sollte die ISP Frequency auf 115.2kHz eingestellt sein.

Bluecontroller - Atmel Studio Main.png

In den Fuses muss gegenfalls noch unter SUT_CKSEL das internen 8 MHz Oszilloskop eingestellt sein.

Bluecontroller - Atmel Studio Fuses.png

AVR-GCC Code

Den vollständigen Code als Atmel Studio 6 Projekt findest du auf GitHub unter Bluecontroller_BCA8_BTM.

Verbindungen testen

Zum Testen (schaltet die eine LED aus bzw. an)

/*
 * test.c
 *
 * Program: AVR Studio 4
 * Author: Fabi
 *
 * Dieses Programm dient nur zum Testen, ob ein Programm erfolgreich
 * auf den Bluecontroller (BCA8-BTM) überspielt werden kann.
 *
 * Es schaltet lediglich eine der beiden LED's aus bzw. an ('an' ist
 * hierbei auskommentiert).
 */
#include <avr/io.h>

void main(void)
{

    DDRB |= (1<<DDB6);
    PORTB = (0<<PB6);
    /* PORTB |= (1<<PB6); */
	
    while (1) {
        // 
    }
}

UART

Ausführliche Hilfe: AVR-GCC - UART

UART Einstellungen[1][2]

Einstellung Wert
CPU clock 8MHz
Baud rate 19200bps
Data bit 8
Stop bit 1
Parity none
Flow control none (oder H/W)

uart.h

/**
 * @file	uart.h
 * @author	Florian Thaeter, Fabi Rosenthal
 * @version	Epsilon
 * @date	25.03.2013
 *
 * @section LICENSE
 *  Licence: CC BY 3.0 (http://creativecommons.org/licenses/by/3.0/)
 *
 * @section DESCRIPTION
 *  Code: http://github.com/Xennis/Bluecontroller_BCA8_BTM
 *
 *  Documentation: http://wiki.xennis.de/artikel/Bluecontroller
 */ 
#ifndef UART_H_
	#define UART_H_

	/* Define */
	#define MCU     atmega328p
	/** FOSC / Clock Speed (ATmega328P) */
	#define F_CPU	8000000UL 
	/** Baud rate (Bluecontroller) */
	#define BAUD	19200
	/** MYUBRR = 25 */
	#define MYUBRR	F_CPU/16/BAUD-1

	/* Include */
	#include <avr/io.h>
	#include <avr/interrupt.h>		// Used for sei(), cli() and ISR()

	/* Register names USART0 */
	#define UBRRH	UBRR0H
	#define UBRRL	UBRR0L

	#define UCSRA	UCSR0A
	#define UCSRB	UCSR0B
	#define UCSRC	UCSR0C

	#define UDR	UDR0
	#define UDRE	UDRE0
	#define UPE	UPE0

	#define DOR	DOR0
	#define FE	FE0
	#define RXC	RXC0
	#define TXB8	TXB80

	/* Method */
	void uart_init(unsigned int ubrr);
	void uart_putc(unsigned char data);

#endif /* UART_H_ */

uart.c

/**
 * @file	uart.c
 * @author	Florian Thaeter, Fabi Rosenthal
 * @version	Epsilon
 * @date	25.03.2013
 *
 * @section LICENSE
 *  Licence: CC BY 3.0 (http://creativecommons.org/licenses/by/3.0/)
 *
 * @section DESCRIPTION
 *  Code: http://github.com/Xennis/Bluecontroller_BCA8_BTM
 *
 *  Documentation: http://wiki.xennis.de/artikel/Bluecontroller
 */
#include "uart.h"

/**
 * UART Initialization
 *
 *	USART Initialization (datasheet page 178)
 */
void uart_init( unsigned int ubrr )
{
	/* Set baud rate */
	UBRRH = (unsigned char)(ubrr>>8);
	UBRRL = (unsigned char)ubrr;
	
	/* Set double speed */
	UCSRA = (0<<U2X0);
	/* Enable receiver, transmitter and UART RX Complete Interrupt (activate global interrupt flag necessary) */
	UCSRB |= (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
	/* Set frame format: 8data, 1stop bit */
	UCSRC |= (1<<UCSZ01)|(1<<UCSZ00);
	
	/* Dummy read to clear UDR */
	UDR;
}

/**
 * Send char
 *
 *	Sending Frames with 5 to 8 Data Bit (datasheet page 179)
 */
void uart_putc( unsigned char data )
{
	/* Wait for empty transmit buffer */
	while ( !( UCSRA & (1<<UDRE) ) );
	/* Put data into buffer, sends the data */
	UDR = data;
}

Bluecontroller

bluecontroller.h

/**
 * @file	bluecontroller.h
 * @author	Fabi Rosenthal
 * @version	Epsilon
 * @date	25.03.2013
 *
 * @section LICENSE 
 *  Licence: CC BY 3.0 (http://creativecommons.org/licenses/by/3.0/)
 *
 * @section DESCRIPTION
 *  Code: http://github.com/Xennis/Bluecontroller_BCA8_BTM
 *
 *  Documentation: http://wiki.xennis.de/artikel/Bluecontroller
 */
#ifndef BLUECONTROLLER_H_
	#define BLUECONTROLLER_H_

	/* Include */
	#include "uart.h"		// Defines F_CPU => important to include before <util/delay.h>
	#include <inttypes.h>
	#include <avr/io.h>
	#include <util/delay.h>

	/* Define (BC=Bluecontroller) */
	
	/** PIN 19 (PB6): LED */
	#define BC_PIN_LED		PINB6 
	/** PIN 20 (PB7): BT-Reset */
	#define BC_PIN_RESET	PINB7
	#define BC_RESET_PORT	PORTB
	#define BC_RESET_PIN	PINB
	#define BC_RESET_DDR	DDRB
	/** Delay (in ms) after send a char */
	#define BC_PUTC_DELAY	10
	/** Activate bt_debug method */
	#define BC_DEBUG

	/* Method */
	void bt_init(void);
	void bt_setut(void);
	void bt_reset(void);
	void bt_turn_off(void);
	void bt_turn_on(void);
	void bt_escape_sequence(void);
	void bt_putc(char c);
	void bt_puts(char* s);
	void bt_send_cmd(char* s);
	//uint8_t bt_check_turn_off(void);
	void bt_debug(char* s);
	void bt_led_on(uint8_t i);

#endif /* BLUECONTROLLER_H_ */

bluecontroller.c (verwendet Methoden von Michael Dreher[3])

/**
 * @file	bluecontroller.c
 * @author	Fabi Rosenthal, Michael Dreher (see note)
 * @version	Epsilon
 * @date	25.03.2013
 *
 * @section LICENSE
 *  Licence: CC BY 3.0 (http://creativecommons.org/licenses/by/3.0/)
 *
 * @section DESCRIPTION
 *  Code: http://github.com/Xennis/Bluecontroller_BCA8_BTM
 *
 *  Documentation: http://wiki.xennis.de/artikel/Bluecontroller
 *
 * Note: 
 * This file uses methods, which are Copyright (c) by Michael Dreher
 * Source: http://code.google.com/r/michaeldreher42-bluecontroller/source/browse/bluecontroller/examples/Setup_BlueController/Setup_BlueController.pde
 *
 * This sketch only works, when __no__ Bluetooth connection is established or when the escape sequence is __not__ disabled
 *
 * Additionally this is a demo of new bootloader functions:
 *   soft_reset() (works with optiboot and other bootloaders which clear the wdt and MCUSR)
 *   enter_bootloader() (works only with BlueController optiboot bootloader and magic-word mechanism)
 */  
#include "bluecontroller.h"

/**
 * Initialization
 *
 *	Initialize Bluecontroller
 */
void bt_init(void)
{
	/* UART and timer */
	uart_init(MYUBRR);
	sei();
	_delay_ms(100);
	
	bt_debug("init");
}

/**
 * Setup
 *
 *	Setup Bluetooth module
 */
void bt_setut(void)
{
	/* Terminate the current Bluetooth connection. */
	bt_reset();

	/* these setting make the connection as transparent as possible */
	bt_send_cmd("\rAT"); // make sure the module is not in sleep mode
	bt_send_cmd("ATE0"); // disable echo
	bt_send_cmd("ATQ1"); // disable result code
	bt_send_cmd("ATC1"); // enable flow control: without this, avrdude under Windows will hang
	bt_send_cmd("ATR1"); // device is slave  
	bt_send_cmd("ATN=Bluecontroller"); // set new name
	bt_send_cmd("ATP=1234"); // set PIN
	bt_send_cmd("ATD0"); // accept connections from any bt device
	bt_send_cmd("ATX0"); // disable escape character (default)
	//bt_send_cmd("ATS1"); // enable power down of rs-232 driver (default)
	bt_send_cmd("ATO"); // reconnect to peer

	/* Allow module to save setting in flash */
	_delay_ms(1000);
	/* Activate new settings */
	bt_reset();
	
	bt_debug("reset");
}

/**
 * Reset the Bluetooth module
 *
 *	This terminates the current Bluetooth connection.
 */
void bt_reset(void)
{
	bt_turn_off();
	bt_turn_on();
}

/**
 * Turn off Bluetooth module
 *
 *	Turns off Bluetooth module
 */
void bt_turn_off(void)
{
	BC_RESET_DDR |= (1<<BC_PIN_RESET);
	BC_RESET_PORT &= ~(1<<BC_PIN_RESET);
	_delay_ms(50);
}

/**
 * Turn on Bluetooth module
 *
 *	Turns on the Bluetooth module
 */
void bt_turn_on(void)
{
	BC_RESET_PORT |= (1<<BC_PIN_RESET);
	BC_RESET_DDR &= ~(1<<BC_PIN_RESET);
	/* Wait until the module is up and running */
	_delay_ms(6000);
}

/**
 * Send escape sequence
 *
 *	Sends escape sequence (+++)
 */
void bt_escape_sequence(void)
{
	_delay_ms(1200);
	bt_puts("+++");
	_delay_ms(1200);  
}

/**
 * Send a character
 *
 *		Sends a character
 *
 * @param c character
 */
void bt_putc(char c)
{
	uart_putc(c);
	/* Slow down communication for BTM-222 */
	_delay_ms(BC_PUTC_DELAY); 
}

/**
 * Send a string
 *
 *	Sends a string (char*)
 *
 * @param s string
 */
void bt_puts(char* s)
{
	/* While *s != '\0' so unequally "string-end characters" (terminator) */
	while(*s) {
 		bt_putc(*s);
		s++;
	}
}

/**
 * Send a command
 *
 *	Sends a Bluecontroller command (needed for setup)
 *
 * @param s string
 */
void bt_send_cmd(char* s)
{
	bt_puts(s);
	/* Carriage return at end (ASCII 13) */
	bt_putc('\r');
}

/**
 * Debug method
 *
 *	Send a string, if debug is on.
 *
 * @param s string
 */
void bt_debug(char* s)
{
	#ifdef BC_DEBUG
		bt_puts("BC_");
		bt_puts(s);
	#endif
}

/*
 * Wait and check, if no command to keep it on
 *
 * @return 1 wenn aktiv, 0 wenn nicht aktiv
 */
/*uint8_t bt_check_turn_off( void )
{
	uint8_t i;
	uint8_t	bt=0;
	DDRB |= (1<<DDB7);
	PORTB |= (1<<PORTB7);
	for (i = 30; i> 1; i--) {
		_delay_ms(1000);
		if ( !(PIND & (1<<PIND2)) ) {
			bt=1;
			i=1;
			_delay_ms(250);	
		}
	}
	// if(bt==0) { ... off
	return bt;
}*/

/**
 * Turn LED on or off
 *
 *	Turns LED on (i==1) / off (i!=1).
 *
 * @param i If i==1 turn LED on, else off
 */
void bt_led_on(uint8_t i)
{
	BC_RESET_DDR |= (1<<BC_PIN_LED);
	if(i == 1) {
		BC_RESET_PORT = (1 << BC_PIN_LED);
	} else {
		BC_RESET_PORT = (0 << BC_PIN_LED);
	}
	
}

Commands

Die beiden Command (CMD) Dateien dienen zum Empfangen und Verarbeiten von Befehlen in Form von Strings.

Befehle Beschreibung
wusel Antwort xyz, dien als Handshake
ledOn Schalte die LED auf dem Board an
ledOff Schalte die LED auf dem Board aus
* Bei jedem nicht bekannten Befehl, wird dieser (nur im Debug-Modus) zurückgeschickt

cmd.h

/**
 * @file	cmd.h
 * @author	Florian Thaeter, Fabi Rosenthal
 * @version	Epsilon
 * @date	25.03.2013
 *
 * @section LICENSE
 *  Licence: CC BY 3.0 (http://creativecommons.org/licenses/by/3.0/)
 *
 * @section DESCRIPTION
 *  Code: http://github.com/Xennis/Bluecontroller_BCA8_BTM
 *
 *  Documentation: http://wiki.xennis.de/artikel/Bluecontroller
 */ 
#ifndef CMD_H_
	#define CMD_H_

	/* Include */
	#include "bluecontroller.h"
	#include <string.h>		// Used for strcmp()

	/* Define */
	#define UART_MAXSTRLEN	10

	/* Method */
	void checkCmd(void);

#endif /* CMD_H_ */

cmd.c

/**
 * @file	cmd.c
 * @author	Fabi Rosenthal, Florian Thaeter
 * @version	Epsilon
 * @date	25.03.2013
 *
 * @section LICENSE
 *  Licence: CC BY 3.0 (http://creativecommons.org/licenses/by/3.0/)
 *
 * @section DESCRIPTION
 *  Code: http://github.com/Xennis/Bluecontroller_BCA8_BTM
 *
 *  Documentation: http://wiki.xennis.de/artikel/Bluecontroller
 */ 
#include "cmd.h"

/* Global Variables */
volatile char uart_string[UART_MAXSTRLEN + 1] = "";	//used to store incoming commands
volatile uint8_t uart_str_complete = 0;     		//1 means complete received
volatile uint8_t uart_str_count = 0;


/**
 * Check commands
 *
 *	This method checks if received command is a valid command and react to it.
 *	Furthermore it resets the commandBuffer.
 */
void checkCmd()
{
	while (uart_str_complete!=1);	//wait for complete command
	
	char* uart_string_val = (char *) uart_string;
	if(strcmp(uart_string_val, "wusel") == 0) {
		bt_puts("xyz");
	}
	else if(strcmp(uart_string_val, "ledOn") == 0) {
		bt_puts("abc");
		bt_led_on(1);
	}
	else if(strcmp(uart_string_val, "ledOff") == 0) {
		bt_puts("123");
		bt_led_on(0);
	}
	else {
		// send invalid command back
		bt_debug(uart_string_val);
	}

	uart_str_complete = 0;			// reset command
	sei(); // TODO: test
}


/**
 * Interrupt USART_RX_vect
 *
 *	This interrupt is fired if new data is available in USART receive buffer.
 *
 *	Source: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART
 */
ISR( USART_RX_vect )
{
	unsigned char nextChar;
	/* Read data from buffer */
	nextChar = UDR;
	//readCmd(nextChar);
	if( uart_str_complete == 0 ) {	// only if uart_string is currently not in use
		if( nextChar != '\n' &&
		nextChar != '\r' &&
		uart_str_count < UART_MAXSTRLEN ) {
			uart_string[uart_str_count] = nextChar;
			uart_str_count++;
		}
		else {
			uart_string[uart_str_count] = '\0';
			uart_str_count = 0;
			uart_str_complete = 1;
			cli(); // TODO: TESTEN
		}
	}
}

Main

Epsilon.c

/**
 * @file	Epsilon.c
 * @author	Fabi Rosenthal, Florian Thaeter
 * @version	Epsilon
 * @date	25.03.2013
 *
 * @section LICENSE
 *  Licence: CC BY 3.0 (http://creativecommons.org/licenses/by/3.0/)
 *
 * @section DESCRIPTION 
 *	Code: http://github.com/Xennis/Bluecontroller_BCA8_BTM
 *
 *  Documentation: http://wiki.xennis.de/artikel/Bluecontroller
 *
 *	Program: Atmel Studio 6
 */
#include "cmd.h"

/**
 * Main
 *
 *	Initializes Bluecontroller and checks the commands.
 */
void main(void)
{
	bt_init();

	/* Write data persistent EEPROM/Flash => only necessary one time */
	//bt_setut();
	
	while(1) {
		checkCmd();
	}
}

Kommunikation zwischen Bluecontroller und PC

Windows

Verbindung mit Bluetooth-Modul (BTM-222) herstellen

Ausführliche Hilfe: Connecting BTM-222 (Windows XP, Linux und Android)

  • (Windows 7) Rechtsklick auf das Bluetooth Symbol in der unteren rechten Liste > Gerät hinzufügen > den Bluecontroller auswählen > Weiter > Kopplungscode des Geräts eingeben > 1234 als Code eintippen > Weiter

Wenn du nun erneut einen Rechtsklick auf das Bluetooth Symbol machst und Bluetooth-Netzwerkgeräte anzeigen auswählst, sollte dort nun der Bluecontroller aufgelistet werden.

COM-Nummer herausfinden

  • Rechtsklick auf Bluetooth Symbol in der unteren rechen Liste > Einstellungen öffnen > COM-Anschlüsse

Dies sollte etwa wie folgt aussehen:

Bluecontroller - Bluetooth-Einstellungen.png

Der gesuchte COM-Anschluss ist der mit der Richtung Ausgehend des Bluecontrollers (der in unserem Fall blub heißt), d.h. COM5.

Terminal

Mithilfe des RS232 Terminal (siehe oben) kannst du Text bzw. Bytes senden und empfangen.

Bluecontroller - RS232 Terminal Einstellungen.png

Neben den benötigten Einstellungen ist auch schon das Ergebnis zu sehen. Der Mikrocontroller sendet regelmäßig ein Was. Schickt man ein x, antwortet er mit einem hallo und einem x dahinter.

Linux (KDE)

Unter Linux kann zum Beispiel das KDE Programm BlueDevil verwendet werden.

  • Installiere BlueDevil
atp-get install bluedevil
  • Starte das Programm und koppel den PC mit dem Bluecontroller (Kopplungscode ist standardmäßig 1234)
  • Verwende das Terminal um den Bluecontroller an einem bestimmten Port einzuhängen (in dem Beispiel ist dieses rfcomm0)
rfcomm bind 0 MAC-ADRESSE -BLUECONTROLLER

Anwendungen

Qt (Raspberry Pi)

Fehler und Tipps

Kommunikation via UART funktioniert nicht

Problem

Mithilfe des UART-Terminals werden keine Strings empfangen beziehungsweise der Bluecontroller reagiert nicht auf versendete Strings.

Lösung

Versorge den Bluecontroller mit Strom an den dafür vorgesehenen Pins und stelle sich, dass der Programmer nicht angeschlossen ist. Denn ist dieser zusätzlich oder ausschließlich angeschlossen, können keine Nachrichten gesendet oder empfangen werden.

Bluecontroller kann nicht mit Programm geflasht werden

Problem

Beim Überspielen der hex-Datei auf den Bluecontroller erscheint eine (ISP) Fehlermeldung und das Programm kann nicht erfolgreich überspielt werden.

Lösung

Der Grund hierfür sein, dass eine aktive Bluetooth-Verbindung besteht. Halte während des gesamten Überspielens den Reset-Knopf auf dem Bluecontroller gedrückt.

Einstellungen (bt_setup) werden nicht übernommen

Um die Einstelungen des Bluetooth Modus zuändern, d.h. die AT-Befehle zu senden, darf keine Bluetooth-Verbindung bestehen. Wir sind dabei wie folgt vorgegangen

  • [Bluetooth Adapter am Computer deaktivieren (um sicherzugehen)]
  • Stromversorgung entfernen und Programmer an den Bluecontroller anstecken
  • Programm überspielen und warten bis die Bluetooth Status LED schnell blinkt
  • Programmer wieder abstecken und kurz warten
  • Stattdessen wieder die Stromversorgung schlißenan und warte kurz
  • [Bluetooth Adapter am PC aktivieren]

Nun sollten die neuen Einstellungen, wie etwa der Name, übernommen wurden sein und dementsprechend (im Falle des Namens) am PC angezeigt werden.

Einzelnachweise

Siehe auch