bitbank2 / ss_oled

Simple and small library to control 1-bpp OLED displays (Linux + Arduino)
GNU General Public License v3.0
190 stars 34 forks source link

Bug with ATTiny85 #15

Closed JanekLeVert closed 5 years ago

JanekLeVert commented 5 years ago

Hi,

First of all I have to say that you're doing a fantastic job so just keep up the good work man.

That said I identified a bug in your ss_oled.cpp code int the following situation:

Context:

Compiling problem: I have an error related to SPI that is not declared in _I2CWrite when in Arduino. There is this code: I put in bold the code that generates the compiling error.

// Wrapper function to write I2C data

ifdef LINUX

static void _I2CWrite(unsigned char *pData, int iLen) { write(file_i2c, pData, iLen); }

else // Arduino

static void _I2CWrite(unsigned char *pData, int iLen) { if (iCSPin != -1) // we're writing to SPI, treat it differently { digitalWrite(iDCPin, (pData[0] == 0) ? LOW : HIGH); // data versus command digitalWrite(iCSPin, LOW);

ifdef HAL_ESP32_HALH

{ uint8_t ucTemp[1024]; SPI.transferBytes(&pData[1], ucTemp, iLen-1); }

else

**SPI.transfer(&pData[1], iLen-1);**

endif

digitalWrite(iCSPin, HIGH);

} else // must be I2C { I2CWrite(oled_addr, pData, iLen); } // I2C } / _I2CWrite() /

endif // LINUX

To avoid having this compiling error I added compilation directives:

// Wrapper function to write I2C data

ifdef LINUX

static void _I2CWrite(unsigned char *pData, int iLen) { write(file_i2c, pData, iLen); }

else // Arduino

static void _I2CWrite(unsigned char *pData, int iLen) { if (iCSPin != -1) // we're writing to SPI, treat it differently { digitalWrite(iDCPin, (pData[0] == 0) ? LOW : HIGH); // data versus command digitalWrite(iCSPin, LOW);

ifdef HAL_ESP32_HALH

{ uint8_t ucTemp[1024]; SPI.transferBytes(&pData[1], ucTemp, iLen-1); }

else

#ifndef __AVR_ATtiny85__ SPI.transfer(&pData[1], iLen-1); #endif

endif

digitalWrite(iCSPin, HIGH);

} else // must be I2C { I2CWrite(oled_addr, pData, iLen); } // I2C } / _I2CWrite() /

endif // LINUX

and now it compiles and I think there's no impact on the way it works as iCSPin should be equal to -1 BUT it does not work. I have no display on my I2C 128x64 LCD.

Here are pictures of the circuit:

alt tag alt tag alt tag

bitbank2 commented 5 years ago

I fixed the regression bug: https://github.com/bitbank2/ss_oled/commit/1b5d9aed2beea5b064ae2fc8c7c9a7c4c2695d70

As far as not working, it's hard to diagnose from what you've shared. For ATtiny85, use the port pin numbering. e.g. instead of pin 0, use 0xb0 (PORTB, bit 0). This will use my faster direct-port access code.

JanekLeVert commented 5 years ago

I tested my ATtiny to verify pin 0 and 2 work well and they do. I tested once again your code on the Arduino Mega (pin 20 and 21) and it works well. Both code call I2CWrite(oled_addr, pData, iLen); but one works, the other doesn't. The difference between the 2 circuits is the microcontroller:

Arduino Mega 2560:

ATtiny85:

I would be very interested to see screenshot of your circuit where I can pins on your attiny85 and pins one your I2C display.

Here is mine: ATtiny point is to the bottom right so that you know in which direction it is. alt tag

bitbank2 commented 5 years ago

There's a big difference between specifying pin 0 and pin 0xb0 in my code (see the bitbang code which gets called to output I2C data). Share your sketch in its entirety; perhaps you're not initializing it correctly.

JanekLeVert commented 5 years ago

Thanks for helping me solving that problem (I love your lib):

Just use your own code: simple_demo_avr.ino

//
// Small Simple OLED library demo for AVR platform,
// without line drawing function (saving of 1K RAM)
//
#include <ss_oled.h>

void setup()
{
    int rc;
    //rc = oledInit(OLED_128x64, 0, 0, -1, -1, 400000L);       // Standard HW I2C bus at 400Khz
    rc = oledInit(OLED_128x64, 0, 0, 0xb0, 0xb2, 400000L); // for ATtiny85, use P0 as SDA and P2 as SCL
    //rc = oledInit(OLED_128x64, 0, 0, 20, 21, 400000L); // for Arduino Mega2560

    if (rc != OLED_NOT_FOUND)
    {
        char *msgs[] =
        {
          "SSD1306 @ 0x3C",
          "SSD1306 @ 0x3D",
          "SH1106 @ 0x3C",
          "SH1106 @ 0x3D"
        };

        oledFill(0, 1);
        oledWriteString(0, 0, 0, (char *)"OLED found:", FONT_NORMAL, 0, 1);
        oledWriteString(0, 10, 2, msgs[rc], FONT_NORMAL, 0, 1);
        delay(3000);
    }
}

void loop()
{
    int i, x, y;

    oledFill(0, 1);
    oledWriteString(0, 16, 0,(char *)"ss_oled Demo", FONT_NORMAL, 0, 1);
    oledWriteString(0, 0, 1,(char *)"Written by Larry Bank", FONT_SMALL, 1, 1);
    oledWriteString(0, 0, 3,(char *)"**Demo**", FONT_STRETCHED, 0, 1);
    oledWriteString(0, 9, 6,(char *)"for AVR", FONT_STRETCHED, 0, 1);

    delay(2000);
    oledFill(0, 1);

    for (i = 0; i < 1000; i++)
    {
        x = random(128);
        y = random(64);
        oledSetPixel(x, y, 1, 1);
    }

    delay(2000);
}
bitbank2 commented 5 years ago

Looks like you might be specifying the wrong pins. From the photo, it looks like you've got SDA connected to PB0 (0) and SCL connected to PB1 (1). attiny85-pinout Try using different pins in case one of them is used for USB and interfering with I2C usage.

JanekLeVert commented 5 years ago

My photo was not taken from the right angle. Here is a better one. You'll see that SDA in on PB0 and SCL on PB2.

alt tag

In this picture we have:

I really don't understand the problem. Could it be the frequency when plugged to ATtiny85 that I remind you I set to 8Mhz instead of 1Mhz? Or maybe there's something to activate on ATtiny to make PB0 and PB2 to work with SDA/SCL. I don't know.

When you say try using different pins I don't see what I can do as I used mandatory pins. What I will test is testing ATtiny outside of the programmer.

JanekLeVert commented 5 years ago

Just tested it outside of the programmer and still does not work. Photo of the circuit.

alt tag

bitbank2 commented 5 years ago

You can use any GPIO pins to drive the display. The speed of the ATtiny85 should not be a problem (fast or slow will work fine). I'm not sure why you're having difficulty. Are you using the Digispark bootloader and dev environment in the Arduino IDE? That's what I tested it on.

JanekLeVert commented 5 years ago

Dev environment is the Arduino IDE. I'm using this programer: https://www.gotronic.fr/art-programmateur-tiny-avr-20210.htm <-- very convenient and works very well.

JanekLeVert commented 5 years ago

WOWWWWWWW That is just incredible. Using pin 3 and 4 instead made the job as you suggested. Thank you very much @bitbank2 that does the job. As said Wonderfull library.

Thank you very much for your support.

bitbank2 commented 5 years ago

Glad you got it working.

JanekLeVert commented 5 years ago

Thanks to you :-D I have one general question. I just tried to make it working on a battery (3V) by connecting GND and VCC to it and nothing happens. It was working with 3.3V with the Arduino. Are you aware of any constraint related to voltage when using ATtiny85+Oled display?

bitbank2 commented 5 years ago

If your OLED display has a 3.3v regulator connected to the Vcc pin (most do), sending 3.0v into a 3.3v regulator will result in output that is too low (or off) to make it work. I would suggest bypassing the regulator and feed the 3.0v directly into the chip.

JanekLeVert commented 5 years ago

I've seen that the OLED screen works the same with 3.3 and 5V. Here is a picture of the backside of the OLED screen.

alt tag

I'm not an electronic expert. Is the regulator what we have between "SELECT" and "U2"? If you were me, where would you connect VCC in this backside assuming that GND can remain where it is?

JanekLeVert commented 5 years ago

I put 2 batteries in serial (3V+3V=6V) ---> still the same ;-(. Poor I am. Once a problem is solved, a new one appears lol

bitbank2 commented 5 years ago

Don't put 6V into the ATtiny85 - it's only rated up to 5.5V. Yes, I believe the 3 pin package is the regulator. You'll need to test the connections to see which pins connect to which part of the regulator (in, gnd, out). If you use one LiPo cell to power your project (3.7-4.2v), then you won't have to worry about this issue. Or use a 3.3v boost converter to convert from 1-1.5v up to 3.3v. I use these in many of my battery powered projects.

JanekLeVert commented 5 years ago

I don't use a LiPo cell. I want to use a small battery, let's say 1x1.5V or 2x1.5V or 1x3V (CR1225 is very small for 3V). It sounds like the solution will be a 3.3 boost converter. I need a tiny one.

bitbank2 commented 5 years ago

This is the kind I use

https://it.aliexpress.com/item/32819454513.html

JanekLeVert commented 5 years ago

Sounds to be a good one. Just the delay that's very long when ordering in aliexpress. If I understand well: I just have to put my batteries (1.5V or 3V) to Vi, GND in the middle and I get 3.3V from Vo knowing that I continue to use GND as usual. Correct?

I was thinking, what is the best, getting a boost converter to 3.3V or to 5V? What is the one that consumes the list amount of energy?

bitbank2 commented 5 years ago

Yes, you understood correctly. This is the wrong place to be teaching you about electricity. Please read my blog post about using batteries with Arduinos:

https://bitbanksoftware.blogspot.com/2019/06/powering-your-arduino-with-batteries.html

JanekLeVert commented 5 years ago

Perfect. I'll go and read your blog asap. :-D

Again thank you very much for your support all the day long. I know it took a lot of your time. Be sure I appreciate.