In case you get one of that cheap clones, everything will work fine until a special situation when things go wrong. Recently, when I wanted to read the internal temperature of the Atmel chip I got extremely strange results. At the end of the day, it turned out that my new UNO was equipped with an ATmega328PB rather than ATmega328P. (I was told that manufacturing of ATmega328PB is somewhat cheaper than its predecessor.) In "Tools -> Board" I had selected "Arduino UNO" and uploading worked fine. But a close look at the board showed: the chip was an ATmega328PB. In the picture shown above the contrast had to be increased heavily to make the label visible. So how could uploading work at all?
The answer was given in a very old posting by Bill Westfield in 2012 titled Burning Bootloader: Expected signature for ATMEGA328P is 1E 95 0F, saying: the bootloader will happily lie to the Arduino IDE and claim to be a 328P. And I can confirm: Bill was right. Well, if you want to run your sketch on any UNO, may it be a real or a fake one, your software should be able to detect the difference.
How can a sketch find out the type of controller?Well, the difference between both chips is the signature of course, but you can not read the signature inside a sketch. Other differences are the extra registers of the ATmega328PB which do not exist inside an ATMEGA328P, for instance the new PORTE register. Unfortunately, if you compile for an ATmega328P the PORTE does not exist. So you have to find its address and check whatever happens if you write and read to this address. The datasheet (see comment) will tell you its address is 0x2E. And this is how it works:
char identifyPB() {
const byte port_E_Address = 0x2E;
for (byte i = 0; i < 0x10; i++) {
/* Serial.print(i); */
/*
set PORTE to i:
see:
Atmel-42397-8-bit-AVR-Microcontroller-
ATmega328PB_Datasheet, page 413
*/
*(volatile byte *) port_E_Address = i;
/* now read PORT E: */
byte j = *(volatile byte *) port_E_Address;
/* Serial.println(j); */
if (i != j) return 0;
}
return 'B';
}
If your chip actually is a real ATmega328P, which does not have a PORTE, writing and reading to this address will do no harm.
So you can call this function in order to identify the kind of board you got by software. I used it in an old sketch of mine where I was reading the internal temperature of the microcontroller when driving a different number of LEDs.
The temperature shown will never be exact, but not taking into account the type of controller will give you very bad results.
Using the OLED you can also go for displaying the values in graphic mode:
This is a close-up:
And this is the code for scrolling:
int v = h - (mean - tempMin) * h1 / (tempMax - tempMin);
y[127] = v;
for (byte x = 1; x < 128; x++) {
byte z = x - 1;
/* do NOT erase the x-axis */
if (y[z] < h1)
oled.drawPixel(x, y[z], BLACK);
y[z] = y[x];
oled.drawPixel(x, y[x], WHITE);
}
Easy, isn't it?
How can you use the extras of a 328PB disguised as a 328P?There are some more differences between ATmega328P and ATmega328PB, see datasheets Electrical Characteristics:
The ATmega328P has three GND pins (marked black and gray), the 328PB only has the black ones. The 328P has two Vcc-pin (marked red and orange), the 328PB only has the red one. The result is, the maximum current it can take went down from 200 mA to 100 mA.
The 328PB has tons of additional registers. If you want to use one of them you just need to find its address. But you should not try to activate any of its new interrupts as their vectors had to be initialized by the compiler.
In case you got a NANO or PRO-MINI where pins A6 and A7 are accessible you may use them as bits 2 and 3 of PORTE (which do not exist in the world of 328P of ourse).
Comments
Please log in or sign up to comment.