POSTS
Week 10: Output Devices
The long term goal is to send data from my load cell and pot to an SD card and then printed out results on an OLED screen.
For this week I just played around with the oled screen and got it to work.
In section 10.1.1 of the attiny44 datasheet, there’s a few paragraphs explaining how to configure pins and how to use, if necessary, the internal pull up resistors.
“Each port pin consists of three register bits: DDxn, PORTxn, and PINxn. As shown in “Register Description” on page 65, the DDxn bits are accessed at the DDRx I/O address, the PORTxn bits at the PORTx I/O address, and the PINxn bits at the PINx I/O address. The DDxn bit in the DDRx Register selects the direction of this pin. If DDxn is written logic one, Pxn is configured as an output pin. If DDxn is written logic zero, Pxn is configured as an input pin. If PORTxn is written logic one when the pin is configured as an input pin, the pull-up resistor is activated. To switch the pull-up resistor off, PORTxn has to be written logic zero or the pin has to be configured as an output pin. The port pins are tri-stated when reset condition becomes active, even if no clocks are running. If PORTxn is written logic one when the pin is configured as an output pin, the port pin is driven high (one). If PORTxn is written logic zero when the pin is configured as an output pin, the port pin is driven low (zero).”
This is the section of the code that I changed (both pins and internal pull up resistors)
#define I2C_delay() _delay_us(5)
#define SCL_pin (1 << PA6)
#define SCL_pins PINA
#define SCL_port PORTA
#define SCL_direction DDRA
#define SDA_pin (1 << PA7)
#define SDA_pins PINA
#define SDA_port PORTA
#define SDA_direction DDRA
void SCL_write(char bit) {
//
// write SCL bit
//
if (bit == 0) {
clear(SCL_port,SCL_pin);
output(SCL_direction,SCL_pin);
clear(SCL_port,SCL_pin);
}
else {
input(SCL_direction,SCL_pin);
// internal pull up
set(SCL_port, SCL_pin);
//
while (pin_test(SCL_pins,SCL_pin) == 0); // check for clock stretching
}
}
void SDA_write(char bit) {
//
// write SDA bit
//
if (bit == 0) {
clear(SDA_port,SDA_pin);
output(SDA_direction,SDA_pin);
clear(SDA_port,SDA_pin);
}
else
input(SDA_direction,SDA_pin);
// internal pull up resistors
set(SDA_port, SDA_pin);
//
}
The first time around, nothing worked.
I made sure to go back and check that the slave address matched the one on my OLED and it did:
In section 8.1.5 of the SSD1306 datasheet, it tells you what the slave addresses are: “SA0” bit provides an extension bit for the slave address. Either “0111100” or “0111101”, can be selected as the slave address of SSD1306. D/C# pin acts as SA0 for slave address selection.
I check on an oscilloscope as well to see what the SCL and SDA signals were doing- they looked like this:
I couldn’t exactly tell what SDA was doing but the clock seemed to be working okay. I was also using an attiny44 not a 45 so maybe there was s flaw somewhere in that change. I checked the fuse bytes as well. Here’s a table from the tiny44 datasheet showing what the fuse bytes should be set to, you can see it matches the table for the attiny45.
I started running out of time and instead just used the board Neil designed which uses a attiny45. I also realized I was going to unrealistic levels of hacking at this point with my board and it was time for a new board.
I designed a new board in eagle and instead of using the alternating header pins like Neil’s board I used the normal header pins with some 0 ohm resistors to act as jumpers to deal with trace difficulties.
I milled the board using the othermill, then soldered components on and plugged everything in. Nothing worked at first because ground and power were shorted- some traces on the edge of the board were connected to the oled header pins. I scratched the connections and tried again and I got the green light on my programmer signaling that my board was getting power.
I ran the oled code provided by neil, this time untouched because my board was the exact same as his example and the oled screen successful displayed!