Hallo Radiofreunde,
anbei möchte ich Euch an einem kleinen Projekt teilhaben lassen. Wie die Überschrift es sagt, geht es in dem Projekt
um die Verwendung eines Mikrocontrollers und eines Graphikdisplays.
Im Unterschied zu vielen im Forum vorgestellten Projekten verwende ich nicht die Arduino Programmierumgebung.
Ich möchte selbst herausfinden was unbedingt nötig ist, um z. B. ein magisches Auge durch moderne Komponenten zu ersetzen.
Nicht zuletzt schreibe ich diesen Thread, weil mich unser Mitglied Bernhard45 mit seinen tollen Beiträgen über den
Ersatz magischer Augen neugierig machte.
Vielleicht erkennt der Leser durch diesen ausführlichen Thread ein wenig besser, welche Leistung Bernhard45 erbracht hat,
und kann diese Erfahrungen eventuell für eigene Projekte nutzen.
Ich beginne mit der Auswahl des Mikrocontrollers. Da sonst überwiegend auf Arduino(s) zurückgegriffen wird, entscheide ich
mich für einen Controller vom Typ ATmega32. Er hat einen Programmspeicher von 32kByte, einen SRAM-Speicher von
2kByte Größe und ähnelt damit dem ATmega328P des weit verbreiteten Arduino nano.
Das sollte für erste Tests mehr als ausreichen.
Beim Display sieht es finster aus - ich habe keins - und frage einen Freund, ob er mir eins ausleihen könnte.
Das Display ist monochrom (blauer Hintergrund, weisse Schrift) und hat eine Größe von 1,3 Zoll.
Die Auflösung beträgt 128 x 64 Punkte bzw. Pixel. Die Stromversorgung des Displays ist auf 3,3V oder 5V ausgelegt.
Es wird mittels I2C-Bus über 2 Drähte gesteuert. Insgesamt müssen also (nur) 4 Leitungen angeschlossen werden,
was die Verdrahtung vereinfacht.
Ich benutze für das Projekt ein Entwicklungsboard vom Typ STK500. Bei dem Board sind (fast) alle Pins des Controllers
auf Pfostenstecker 'verdrahtet', so dass ein Versuchsaufbau schnell zusammen gesteckt werden kann.
Das Board besitzt einige Steckplätze zur Aufnahme verschiedenster Mikrocontroller der AVR Familie.
Zusätzlich stellt es 8 Taster zur Signal Eingabe und 8 LEDs zur Ausgabe von digitalen Zuständen bereit.
Die Verbindung zum Rechner erfolgt seriell (mittels eines USB-Seriell Interface).
Das Programm wird mit einem Editor (TextWrangler) geschrieben. Die Programmiersprache ist AVR-GCC.
Der GNU Compiler für AVR (avr-gcc) übersetzt die programmierten Zeilen in den Maschinencode.
Das Programm AVRdude überträgt den Maschinencode in den Programmspeicher des Mikrocontrollers.
Das war die Theorie - jetzt folgt die Praxis!
Wie fange ich an, was brauche ich, um solch ein Display benutzen zu können?
An erster Stelle fehlt jetzt eine Bibliothek zur Ansteuerung des Displays. Bibliotheken (engl. Library) stellen dem Programmierer
u.a. Funktionen unterschiedlichster Art zur Verfügung. Das verkürzt den Programmieraufwand ganz wesentlich.
Eine gute Quelle für Informationen rund um Mikrocontroller ist - oh Wunder - das Mikrocontroller-Forum.
Hier suchte ich nach OLED Display und fand einen passenden Beitrag. Das Besondere an dieser Library (finde ich) ist,
dass sie neben grundsätzlichen Zeichenfunktionen (Linie, Kreis, Rechteck...) auch noch den I2C-Treiber für ein Display enthält.
Vielen Dank an den Author, der zusätzlich ein Beispiel des Hauptprogramms (main.c) veröffentlichte!
Um die Funktionen der Library kennen zu lernen und letztendlich nutzen zu können, lese ich das dazugehörige include-file (lcd_gfx.h).
Die Funktionen
void lcd_init(uint8_t dispAttr);
void lcd_set_contrast(uint8_t contrast);
void lcd_clrscr(void);
void lcd_draw_Line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color);
lcd_display();
sind nötig, um eine Linie auf dem OLED zu erzeugen.
Ich werde sie im Hauptprogramm einbauen.
Anbei zeige ich Euch den Code des Hauptprogramms (main.c), der eine Linie in der Mitte eines OLED Displays erzeugt.
Nach dem Kompilieren erscheint folgende Meldung auf dem Bildschirm:
Bildschirmfoto 2017-06-16 um 16.30.43.png (Größe: 43,82 KB / Downloads: 247)
Das Mini-Programm belegt ganze 2892 Byte im Programmspeicher - erstaunlich wenig.
Linie.JPG (Größe: 75,16 KB / Downloads: 247)
Fortsetzung folgt!
anbei möchte ich Euch an einem kleinen Projekt teilhaben lassen. Wie die Überschrift es sagt, geht es in dem Projekt
um die Verwendung eines Mikrocontrollers und eines Graphikdisplays.
Im Unterschied zu vielen im Forum vorgestellten Projekten verwende ich nicht die Arduino Programmierumgebung.
Ich möchte selbst herausfinden was unbedingt nötig ist, um z. B. ein magisches Auge durch moderne Komponenten zu ersetzen.
Nicht zuletzt schreibe ich diesen Thread, weil mich unser Mitglied Bernhard45 mit seinen tollen Beiträgen über den
Ersatz magischer Augen neugierig machte.
Vielleicht erkennt der Leser durch diesen ausführlichen Thread ein wenig besser, welche Leistung Bernhard45 erbracht hat,
und kann diese Erfahrungen eventuell für eigene Projekte nutzen.
Ich beginne mit der Auswahl des Mikrocontrollers. Da sonst überwiegend auf Arduino(s) zurückgegriffen wird, entscheide ich
mich für einen Controller vom Typ ATmega32. Er hat einen Programmspeicher von 32kByte, einen SRAM-Speicher von
2kByte Größe und ähnelt damit dem ATmega328P des weit verbreiteten Arduino nano.
Das sollte für erste Tests mehr als ausreichen.
Beim Display sieht es finster aus - ich habe keins - und frage einen Freund, ob er mir eins ausleihen könnte.
Das Display ist monochrom (blauer Hintergrund, weisse Schrift) und hat eine Größe von 1,3 Zoll.
Die Auflösung beträgt 128 x 64 Punkte bzw. Pixel. Die Stromversorgung des Displays ist auf 3,3V oder 5V ausgelegt.
Es wird mittels I2C-Bus über 2 Drähte gesteuert. Insgesamt müssen also (nur) 4 Leitungen angeschlossen werden,
was die Verdrahtung vereinfacht.
Ich benutze für das Projekt ein Entwicklungsboard vom Typ STK500. Bei dem Board sind (fast) alle Pins des Controllers
auf Pfostenstecker 'verdrahtet', so dass ein Versuchsaufbau schnell zusammen gesteckt werden kann.
Das Board besitzt einige Steckplätze zur Aufnahme verschiedenster Mikrocontroller der AVR Familie.
Zusätzlich stellt es 8 Taster zur Signal Eingabe und 8 LEDs zur Ausgabe von digitalen Zuständen bereit.
Die Verbindung zum Rechner erfolgt seriell (mittels eines USB-Seriell Interface).
Das Programm wird mit einem Editor (TextWrangler) geschrieben. Die Programmiersprache ist AVR-GCC.
Der GNU Compiler für AVR (avr-gcc) übersetzt die programmierten Zeilen in den Maschinencode.
Das Programm AVRdude überträgt den Maschinencode in den Programmspeicher des Mikrocontrollers.
Das war die Theorie - jetzt folgt die Praxis!
Wie fange ich an, was brauche ich, um solch ein Display benutzen zu können?
An erster Stelle fehlt jetzt eine Bibliothek zur Ansteuerung des Displays. Bibliotheken (engl. Library) stellen dem Programmierer
u.a. Funktionen unterschiedlichster Art zur Verfügung. Das verkürzt den Programmieraufwand ganz wesentlich.
Eine gute Quelle für Informationen rund um Mikrocontroller ist - oh Wunder - das Mikrocontroller-Forum.
Hier suchte ich nach OLED Display und fand einen passenden Beitrag. Das Besondere an dieser Library (finde ich) ist,
dass sie neben grundsätzlichen Zeichenfunktionen (Linie, Kreis, Rechteck...) auch noch den I2C-Treiber für ein Display enthält.
Vielen Dank an den Author, der zusätzlich ein Beispiel des Hauptprogramms (main.c) veröffentlichte!
Um die Funktionen der Library kennen zu lernen und letztendlich nutzen zu können, lese ich das dazugehörige include-file (lcd_gfx.h).
Code:
/*
* This file is part of lcd library for ssd1306/sh1106 oled-display.
*
* lcd library for ssd1306/sh1106 oled-display is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
*
* lcd library for ssd1306/sh1106 oled-display is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*
* Diese Datei ist Teil von lcd library for ssd1306/sh1106 oled-display.
*
* lcd library for ssd1306/sh1106 oled-display ist Freie Software: Sie können es unter den Bedingungen
* der GNU General Public License, wie von der Free Software Foundation,
* Version 3 der Lizenz oder jeder späteren
* veröffentlichten Version, weiterverbreiten und/oder modifizieren.
*
* lcd library for ssd1306/sh1106 oled-display wird in der Hoffnung, dass es nützlich sein wird, aber
* OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
* Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
* Siehe die GNU General Public License für weitere Details.
*
* Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
* Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
*
* lcd.h
*
* Created by Michael Köhler on 22.12.16.
* Copyright 2016 Skie-Systems. All rights reserved.
*
* lib for OLED-Display with ssd1306/sh1106-Controller
* first dev-version only for I2C-Connection
* at ATMega328P like Arduino Uno
****************************************************
* For other Atmegas/Attinys: GFX-Lib needs a
* minimum of 1027 byte SRAM!
****************************************************
*
*/
#ifndef LCD_H
#define LCD_H
#ifndef YES
#define YES 1
#endif
#ifndef NO
#define NO 0
#endif
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 303
#error "This library requires AVR-GCC 3.3 or later, update to newer AVR-GCC compiler !"
#endif
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
/* TODO: define displaycontroller */
#define SSD1306 // or SH1106, check datasheet of your display
//#define SH1106 // or SSD1306, check datasheet of your display
/* TODO: setup pins */
//#define SDA_Pin PC4 // ATmega328p
//#define SDC_Pin PC5 // ATmega328p
#define SDA_Pin PC1 // ATmega32
#define SDC_Pin PC0 // ATmega32
#define LCD_PORT PORTC // LCD haengt an Port C
#define LCD_PORT_DDR DDRC // Daten-Richtungs-Register
/* TODO: setup i2c/twi */
#define LCD_I2C_ADDR 0x78 // refer lcd-manual, 0x78 for 8-bit-adressmode,
// 0x3c for 7-bit-adressmode
#define LCD_INIT_I2C YES // init I2C via lcd-lib
#define F_I2C 400000UL // clock i2c
#define PSC_I2C 1 // prescaler i2c
#define SET_TWBR (F_CPU/F_I2C-16UL)/(PSC_I2C*2UL)
#define LCD_DISP_OFF 0xAE
#define LCD_DISP_ON 0xAF
#define WHITE 0x01
#define BLACK 0x00
#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 64
#define DISPLAYSIZE DISPLAY_WIDTH*DISPLAY_HEIGHT/8 // 8 pages/lines with 128
// 8-bit-column: 128*64 pixel
// 1024 bytes
void i2c_init(void); // init hw-i2c
void lcd_send_i2c_start(void); // send i2c_start_condition
void lcd_send_i2c_stop(void); // send i2c_stop_condition
void lcd_send_i2c_byte(uint8_t byte); // send data_byte
void lcd_init(uint8_t dispAttr); // init display,
// attributes: LCD_DISPLAY_ON,
// LCD_DISPLAY_OFF
void lcd_home(void); // set cursor to (x,y) = (0,0)
void lcd_command(uint8_t cmd[], uint8_t size); // transmit command to display
void lcd_data(uint8_t data[], uint16_t size); // transmit data to display
void lcd_gotoxy(uint8_t x, uint8_t y); // set curser at pos x, y.
// x means character, y means line
// (page, refer lcd manual)
void lcd_clrscr(void); // clear screen
void lcd_putc(char c); // print character on screen
void lcd_puts(const char* s); // print string, \n-terminated, from ram on screen
void lcd_puts_p(const char* progmem_s); // print string from flash on screen
void lcd_puts_e(const char* eemem_s); // print string form eeprom on screen
void lcd_invert(uint8_t invert); // invert display
uint8_t lcd_isInverted(void); // returns YES if display is inverted NO if display isn't inverted
void lcd_set_contrast(uint8_t contrast); // set contrast for display
void lcd_drawPixel(uint8_t x, uint8_t y, uint8_t color);
void lcd_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color);
void lcd_drawRect(uint8_t px1, uint8_t py1, uint8_t px2, uint8_t py2, uint8_t color);
void lcd_fillRect(uint8_t px1, uint8_t py1, uint8_t px2, uint8_t py2, uint8_t color);
void lcd_drawCircle(uint8_t center_x, uint8_t center_y, uint8_t radius, uint8_t color);
void lcd_fillCircle(uint8_t center_x, uint8_t center_y, uint8_t radius, uint8_t color);
void lcd_display(void); // copy buffer to display RAM
//void lcd_drawBitmap(uint8_t px, uint8_t py, const uint8_t bitmap[]); // draw bitmap at pixel position x, y
#endif /* LCD_H */
Die Funktionen
void lcd_init(uint8_t dispAttr);
void lcd_set_contrast(uint8_t contrast);
void lcd_clrscr(void);
void lcd_draw_Line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color);
lcd_display();
sind nötig, um eine Linie auf dem OLED zu erzeugen.
Ich werde sie im Hauptprogramm einbauen.
Anbei zeige ich Euch den Code des Hauptprogramms (main.c), der eine Linie in der Mitte eines OLED Displays erzeugt.
Code:
/*
* Name: main.c
*
* Author: norbert_w
* Darstellung einer Linie in der Mitte eines OLED-Graphik Display
* Auflösung 128 x 64 Pixel, I2C Pin Beschreibung lcd_gfx.h
* MCU ATmega32 F CPU 16MHz
*
*/
#include "main.h"
#include "lcd_gfx.h"
int main(void)
{
// LCD Initialisieren
lcd_init(LCD_DISP_ON);
// LCD Contrast einstellen
lcd_set_contrast(0x0f);
// PB5 als Ausgang schalten (Beim Arduino Uno haengt hier eine LED dran: PIN 13)
DDRB |= (1 << PB5);
// Display löschen
lcd_clrscr();
//Schleife des Hauptprogramms
for(;;){
// LED toggeln, d.h. je Programmdurchlauf abwechselnd ein- bzw. ausschalten
PORTB ^= (1 << PB5);
// zeichnen einer Linie (in den Graphik-Buffer)
lcd_drawLine(0, 31, 127, 31, WHITE);
// Graphik-Buffer anzeigen
lcd_display();
}
}
Nach dem Kompilieren erscheint folgende Meldung auf dem Bildschirm:
Bildschirmfoto 2017-06-16 um 16.30.43.png (Größe: 43,82 KB / Downloads: 247)
Das Mini-Programm belegt ganze 2892 Byte im Programmspeicher - erstaunlich wenig.
Linie.JPG (Größe: 75,16 KB / Downloads: 247)
Fortsetzung folgt!
Grüße aus Wassenberg,
Norbert.
Norbert.