Output devices

This week will work on implementation reading of sensor data. And visualizing of received data using the some chart and data visualization library.

software / sites used during this week

XCode
I will try to use Mac OS X C development IDE to programm Attiny
X-AVR
X-AVR is an XCode template for generating AVR C projects. github link here. Very comfortable way to develop and build using this template (better then crosspack brut).
bCNC
Opensource application to control GRBL CNC machine. Written on python. Accessible via github from here

hardware

Attiny44
1$ 14 pins low power avr controller. Nice for sensor capture projects.
Video display
Video display to make an output
CNC machine
Home made CNC machine. GRBL controlled. Work area about A4 format. Z-axis ~10cm high. Precision - not well enough for real PCB SMC. Multi-proposal - so can be used for vinyl cutting, some kind of PCB, molding...
Roland SRM-20
Micrometric precision CNC milling machine. Simple, quiet and fast in usage.
Attiny45
1$ 8 pins low power avr controller chip. Has enough pins to realize I2C communication that I required in my second attempt.
ssd1306
Small OLED matrix with 128x64 resolution. Managed via I2C interface. I took the double color version (top is yellow and the bottom is blue)

All files that I have demonstrated below are also available in this zip file

Assignments

Add an output device to a microcontroller board you've designed and program it to do something

There was no way this week to make a PCB with microcontroller on it (machine accessibility) so I did a simple board that may be used with any arduino / satchakit or another to send an output to video screen. So first - simple eagle schema and board. On screenshot is newest version that include the large GND surface and bigger traces, but I cutted the first version. It contain connector to arduino / attiny / satchakit board, two resistors (~500Ohm and 1KOhm) and place to solder the cable. I did not found female "tulipe" connector in my warehouse.

Now I try to cut it. I use my own milling machine that does not have enough precision to make a PCB with attiny (tiny traces) but some 0.4+ mm traces are enough well for prototyping. So I use the 0.2mm "Javelin" end-mill for traces, 0.8mm forest for holes, and 2.5mm end-mill for cutout. Below is result.

Visual control for traces, small touch by cutter to clear not-sure locations from rest copper (or just a dust), and go to soldering.

To be continue... (Need a machine to make satchakit, or PCB with attiny44 and then go for programming)

OLED display

Second try for this assignment

Finally the first attempt to realize the assignment was not finished because I did not found the screen with simple video input (like a classic yellow tulipe or vga) around me... All screens are with HDMI, thunderbolt and so on, and the old screen that I thought I have in the garage was completely dead.
So I decided to realize an output device ising the small OLED display that can be useful in my case of final project (it is an optional device that can be connected to glow). And as well I think to implement it in one of sub-projects (soil moisture sensor)

I need a card that will drive my display. So as this OLED display uses the I2C protocol to communicate with it - I will use the I2C card from the network week. It provide exactly that I need to drive the matrix.

Milling the card

Let solder it.

Connection of wires is simple - VCC, GND, SCL and SDA signals only (standard I2C connection without interrupt wire). The I2C protocol is something that I learn about during the networking week.

To draw something on OLED matrix used following idea. Matrix is 128x64 bit map. Each bit if changed from 0 to 1 - switch on related dot on matrix. For addressing bits it is divided into eight pages, from PAGE0 to PAGE7. Each page contain 128 columns (and each column contain 8 bits). From the datasheet we can get following addresing way:
In normal display data RAM read or write and page addressing mode, the following steps are required to: define the starting RAM access pointer location:

  • Set the page start address of the target display location by command B0h to B7h.
  • Set the lower start column address of pointer by command 00h~0Fh.
  • Set the upper start column address of pointer by command 10h~1Fh.
  • For example, if the page address is set to B2h, lower column address is 03h and upper column address is 10h, then that means the starting column is SEG3 of PAGE2. The RAM access pointer is located as shown in Figure 10-2. The input data byte will be written into RAM position of column 3.

    Using this information we can draw a point. But we need a characters, (of course we can draw characters by ourselves) so I will search if any library already exists to pilote the OLED.

    I found following library that permit draw characters and images. Size of RAM in attiny45 is too small to execute the example provided by this library (it show some text example and event image showing on the screen). So I modified a little example (removed part of output image, removed library) and pushed to my card. Here is diffs for the test main.c:

    $ diff main.c main.c.1
    56,57c56,57
    < // #include "img0_128x64c1.h"
    < // #include "img1_128x64c1.h"
    ---
    > #include "img0_128x64c1.h"
    > #include "img1_128x64c1.h"
    149,150c149,150
    < 		// ssd1306_draw_bmp(0,0,128,8, img1_128x64c1);
    < 		// _delay_ms(4000);
    ---
    > 		ssd1306_draw_bmp(0,0,128,8, img1_128x64c1);
    > 		_delay_ms(4000);
    153,154c153,154
    < 		// ssd1306_draw_bmp(0,0,128,8, img0_128x64c1);
    < 		// _delay_ms(6000);
    ---
    > 		ssd1306_draw_bmp(0,0,128,8, img0_128x64c1);
    > 		_delay_ms(6000);
                              
    Then classic - make hex, and use my avrdude and programmer to push it to attiny45.
    Below is result. It works!

    First test of OLED output

    Now let write a real program that will display information for my sub-project of soil moisture sensors (there are 5..6 pots of flowers that controlled by the microcontroller and information we need to collect / store / and display. So diplay is the keyword in this case). I will use the yellow part of my screen as the header (just for an avertising purpose) and the blue part for output lines. 6 lines with numbers that will show watering level for the soil. In my test I decided to show just random numbers, that will be updated each few seconds. So it will show how it should work in the future.
    So here is my code:

    #include <stdint.h>
    #include <avr/io.h>
    #include <util/delay.h>
    #include <stdlib.h>
    
    #define SSD1306_SCL             PB2     // SCL, Pin 3 on SSD1306 Board
    #define SSD1306_SDA             PB0     // SDA, Pin 4 on SSD1306 Board
    
    #define SSD1306_SA              0x78    // Slave address OLED display (cf datasheet)
    
    #include "cpufreq.h"
    
    #include "ssd1306xled.h"      // Library for manage oled screen
    #include "ssd1306xled8x16.h"  // Library with font 8x16 (each character is realized as matrix of dots)
    
    int main(void) {
    
    #if F_CPU == 1000000UL
    #pragma message "F_CPU=1MHZ"
        CLKPR_SET(CLKPR_1MHZ);
    #elif F_CPU == 8000000UL
    #pragma message "F_CPU=8MHZ"
        CLKPR_SET(CLKPR_8MHZ);
    #else
    #pragma message "F_CPU=????"
    #error "CPU frequency should be either 1 MHz or 8 MHz"
    #endif
    
        // Small delay is necessary if ssd1306_init is the first operation in the application.
        _delay_ms(40);
        ssd1306_init();
        ssd1306_clear(); _delay_ms(200);
    
        // Yellow header lines
        ssd1306_setpos(3, 0);  ssd1306_string_font6x8("-=Flowers automate=-");
        ssd1306_setpos(80, 1);  ssd1306_string_font6x8("rku v1.0");
    
        // ---- Main Loop ----
    
        for (;;) {
    
            ssd1306_setpos(25, 2);   ssd1306_string_font6x8("Pot #1: ");
            ssd1306_numdecp(rand() % 1000);
            _delay_ms(1000);
            ssd1306_setpos(25, 3);   ssd1306_string_font6x8("Pot #2: ");
            ssd1306_numdecp(rand() % 1000);
            ssd1306_setpos(25, 4);   ssd1306_string_font6x8("Pot #3: ");
            ssd1306_numdecp(rand() % 1000);
            ssd1306_setpos(25, 5);   ssd1306_string_font6x8("Pot #4: ");
            ssd1306_numdecp(rand() % 1000);
            ssd1306_setpos(25, 6);   ssd1306_string_font6x8("Pot #5: ");
            ssd1306_numdecp(rand() % 1000);
            ssd1306_setpos(25, 7);   ssd1306_string_font6x8("Pot #6: ");
            ssd1306_numdecp(rand() % 1000);
            _delay_ms(6000);
    
        }
    
        return 0;
    }
                            

    Each time I need to show something I send 2 commands - I place the position of my "cursor" - in fact it addressing the bit where will be started the output line, then I send the line. Data is stored in memory of the OLED screen - so it static and will be shown until I will not re-write the line.

    And here is the result