Group Assignment
A microcontroller (MCU) is a compact integrated circuit designed to do a specific operation in an embedded system. A typical microcontroller includes a processor, memory and input/output (I/O) peripherals on a single chip.
MCUs are useless to be used alone. They require to be integrated within as system on sensors, actuators, programmers, power regulation, and more.
A single-board microcontroller is a microcontroller built onto a single printed circuit board. This board provides all of the circuitry necessary for a useful control task: a microprocessor, I/O circuits, a clock generator, RAM, stored program memory and any necessary support ICs. The intention is that the board is immediately useful to an application developer, without requiring them to spend time and effort to develop controller hardware.
I have many MCU boards and I decided to benchmark the core processors of each board.
Arduino Software (IDE) have all Arduino AVR boards installed by default. Some other boards can be programmed from the IDE but they require additional software core to be installed. Cores are necessary to make new microcontrollers compatible with your Arduino Software (IDE) and, possibly, the existing sketches and libraries.
In order to program the Node MCU and Arduino 101; I've Installed the following cores:
I then uploaded to following speed test code on each board and opened the serial port to get the following benchmark data.
// Arduino Speed Test Benchmarking Program
// Original Program Credit: Arduino.cc
// Modified By: Dan Watson
// synchannel.blogspot.com
// 1-29-2015
void setup()
{
Serial.begin(9600);
pinMode(9, OUTPUT);
pinMode(10, INPUT);
Serial.println("Speed Test will begin momentarily.");
Serial.println("");
delay(4000);
speedTest();
}
void loop()
{
// Do nothing
}
void speedTest(void)
{
register int i,j;
volatile unsigned char c1,c2;
volatile int v;
volatile long l1,l2;
volatile float f1,f2;
int p,q;
long int r;
unsigned long m,n;
float d, overhead;
char buffer[30];
Serial.println(F(""));
Serial.println(F("Speed test"));
Serial.println(F("----------"));
Serial.print(F("F_CPU = "));
Serial.print(F_CPU,DEC);
Serial.println(F(" Hz"));
Serial.print(F("1/F_CPU = "));
Serial.print((1000000.0/(float)F_CPU),4);
Serial.println(F(" us"));
delay(800); // Allow the Serial text to be transmitted
Serial.print(F(" nop : "));
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<100; i++)
{
for (j=0; j<10000; j++)
{
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0; // in micro seconds
// Calculate overhead with 'nop' instruction per loop in microseconds
overhead = d - (20.0 * (1000000.0/(float)F_CPU));
d -= overhead;
d /= 20.0; // per instruction
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" digitalRead : "));
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<2; i++)
{
for (j=0; j<10000; j++)
{
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
digitalRead(10);
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" digitalWrite : "));
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<2; i++)
{
for (j=0; j<10000; j++)
{
digitalWrite(12, HIGH);
digitalWrite(12, LOW);
digitalWrite(12, HIGH);
digitalWrite(12, LOW);
digitalWrite(12, HIGH);
digitalWrite(12, LOW);
digitalWrite(12, HIGH);
digitalWrite(12, LOW);
digitalWrite(12, HIGH);
digitalWrite(12, LOW);
digitalWrite(12, HIGH);
digitalWrite(12, LOW);
digitalWrite(12, HIGH);
digitalWrite(12, LOW);
digitalWrite(12, HIGH);
digitalWrite(12, LOW);
digitalWrite(12, HIGH);
digitalWrite(12, LOW);
digitalWrite(12, HIGH);
digitalWrite(12, LOW);
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" pinMode : "));
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<2; i++)
{
for (j=0; j<10000; j++)
{
pinMode(13, INPUT);
pinMode(13, OUTPUT);
pinMode(13, INPUT);
pinMode(13, OUTPUT);
pinMode(13, INPUT);
pinMode(13, OUTPUT);
pinMode(13, INPUT);
pinMode(13, OUTPUT);
pinMode(13, INPUT);
pinMode(13, OUTPUT);
pinMode(13, INPUT);
pinMode(13, OUTPUT);
pinMode(13, INPUT);
pinMode(13, OUTPUT);
pinMode(13, INPUT);
pinMode(13, OUTPUT);
pinMode(13, INPUT);
pinMode(13, OUTPUT);
pinMode(13, INPUT);
pinMode(13, OUTPUT);
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" multiply byte : "));
c1 = 2;
c2 = 3;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<20; i++)
{
for (j=0; j<10000; j++)
{
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
c1 *= c2;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" divide byte : "));
c1 = 253;
c2 = 3;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<2; i++)
{
for (j=0; j<10000; j++)
{
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
c1 /= c2;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" add byte : "));
c1 = 1;
c2 = 2;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<20; i++)
{
for (j=0; j<10000; j++)
{
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
c1 += c2;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" multiply integer : "));
volatile int x,y;
x = 2;
y = 3;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<10; i++)
{
for (j=0; j<10000; j++)
{
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
x *= y;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" divide integer : "));
x = 31415;
y = 3;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<1; i++)
{
for (j=0; j<10000; j++)
{
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
x /= y;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" add integer : "));
x = 1;
y = 3;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<10; i++)
{
for (j=0; j<10000; j++)
{
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
x += y;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" multiply long : "));
l1 = 2;
l2 = 3;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<2; i++)
{
for (j=0; j<10000; j++)
{
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
l1 *= l2;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" divide long : "));
l1 = 2000000000L;
l2 = 3;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<1; i++)
{
for (j=0; j<2000; j++)
{
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
l1 /= l2;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" add long : "));
l1 = 500000000L;
l2 = 123;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<4; i++)
{
for (j=0; j<10000; j++)
{
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
l1 += l2;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" multiply float : "));
f1 = 3.24;
f2 = 1.25;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<2; i++)
{
for (j=0; j<10000; j++)
{
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
f1 *= f2;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" divide float : "));
f1 = 312645.24;
f2 = 1.21;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<1; i++)
{
for (j=0; j<2000; j++)
{
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
f1 /= f2;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" add float : "));
f1 = 9876.54;
f2 = 1.23;
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<1; i++)
{
for (j=0; j<10000; j++)
{
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
f1 += f2;
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" delay(1) : "));
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<1; i++)
{
for (j=0; j<100; j++)
{
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
delay(1);
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.print(F(" delay(100) : "));
delay(70); // Allow the Serial text to be transmitted
m=millis();
for (i=0; i<1; i++)
{
for (j=0; j<2; j++)
{
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
delay(100);
}
}
n=millis();
d = ((float)n - (float)m) / ((float)i * (float)j);
d *= 1000.0;
d -= overhead;
d /= 20.0;
Serial.print (d,3);
Serial.println (F(" us"));
Serial.println(F("-----------"));
}
Arduino UNO | Node MCU | Arduino 101 | |
---|---|---|---|
Controller | ATMega328 | ESP8266 | Intel® Curie™ |
Frequency | 16 MHz | 80 MHz | 32 MHz |
nop | 0.063 us | 0.013 us | 0.031 us |
digitalRead | 4.902 us | 0.540 us | 1.350 us |
digitalWrite | 4.532 us | 0.933 us | 2.132 us |
pinMode | 4.342 us | 1.455 us | 2.630 us |
multiply byte | 0.632 us | 0.100 us | 0.318 us |
divide byte | 5.410 us | 0.400 us | 1.408 us |
add byte | 0.443 us | 0.100 us | 0.284 us |
multiply integer | 1.387 us | 0.148 us | 0.347 us |
divide integer | 14.272 us | 0.438 us | 1.380 us |
add integer | 0.883 us | 0.135 us | 0.284 us |
multiply long | 6.102 us | 0.148 us | 0.347 us |
divide long | 38.662 us | 0.447 us | 1.400 us |
add long | 1.763 us | 0.135 us | 0.285 us |
multiply float | 7.925 us | 0.738 us | 0.377 us |
divide float | 80.162 us | 3.772 us | 0.350 us |
add float | 10.112 us | 0.683 us | 0.380 us |
delay(1) | 1007.487 us | 1024.997 us | 1002.500 us |
delay(100) | 100024.984 us | 100025.000 us | 100000.000 us |
Let me give you a brief about each core in more detail.
The ATmega328/P (found in the Arduino UNO) is a low-power CMOS 8-bit microcontroller based on the AVR® enhanced RISC (reduced instruction set computer) architecture. In Order to maximize performance and parallelism, the AVR uses Harvard architecture – with separate memories and buses for program and data.
The ESP8266 (found in the Node MCU) uses a 32bit processor with 16 bit instructions. It is Harvard architecture which mostly means that instruction memory and data memory are completely separate.
For the Intel® Curie™ module (found in the Arduino 101), it features a dual-core architecture — a host processor and a sensor subsystem — with shared on-die SRAM and flash memory. The host processor is built around a low power 32 MHz Intel® Quark™ SE core, and its instruction set features Intel® archi-tecture and Intel® Pentium® x86 compatibility, with the exception of FPU instructions. Intel have completely given up on its efforts to bring products specific to the Internet of Things. They discontinued the Curie module; along with Intel Edison, Galileo and Joule boards.
The Intel Curie™ seem to be perfect at timing due to its beast dual core processors, and the ESP8266 seem to do more processing in less time because it's attached to much more quick crystal. The ESP8266 can operate up to 160 MHz crystal. I really loved the ESP. I'm goint to use my Node MCU in more future projects.
Understanding ATTiny44
Flash (program memory) | 4096 bytes |
---|---|
RAM | 256 bytes |
EEPROM | 256 bytes |
GPIO Pins | 8 + RST + XTAL1 + XTAL2 |
ADC Channels | 8 |
PWM Channels | 4 |
Clock options | Internal 1/8mhz, external crystal or clock* up to 20mhz |
DDRB = 0b00001111;
PORTB = 0xFF;
will write HIGH on every pin that was set as output.
Arduino-C Code
pinMode
in the void setup()
section, which will be executed once, then write your code sequence in the void loop()
section
and it will run repeatedly. Here are some quotes about the most important functions in the Arduino-C language.
INPUT
or an OUTPUT
. It is possible to enable the internal pullup resistors with the mode INPUT_PULLUP
. Additionally, the INPUT mode explicitly disables the internal pullups.
pinMode(pin, state)
HIGH
or a LOW
value to a digital pin. digitalWrite(pin, value)
HIGH
or LOW
.
digitalRead(pin)
delay(ms)
void setup() {
pinMode(8, OUTPUT);
pinMode(7, INPUT_PULLUP);
}
void loop() {
if (!digitalRead(7))
{
digitalWrite(8, HIGH);
delay(1250);
digitalWrite(8, LOW);
delay(1250);
}
}
digitalRead(7)
returns HIGH
when the button is unpressed because we defined the input pin to be pulled-up, and
it will be inverted so that the If statement won't be executed when the button is not pressed.
digitalRead(7)
returns LOW
which will be inverted by the (!) mark to HIGH
, causing the If statement to execute.
AVR-C Code
#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void)
function, which will be executed directly when the MCU is powered.
Inside this fucntion, we can write any sequence we want for the code. The code written inside the main is executed only for one time.
DDRB = 0b00000100;
line, will configure Pin 2 at Port B as Output.
PORTA = 0b10000000;
line, will Pull-up Pin 7 at Port A.
void setup()
function in the Arduino-C code.
while(1)
infinite loop, where we can nest the condition and the ON/OFF sequence.
if (!(PINA & (0b10000000)))
. The PINA
reads the whole pins byte (A).
In order to read a specifi pin, we should just ignore the rest of the pins by anding them with zeros.
When the required pin is connected to GND the expression result will be !(0) which is 1, and vice versa.
PORTB |= 0b00000100;
to output logic 1 on Pin 2 at Port B; leaving the other pins in whatever state.
This is because (0) | 0 = 0 and (1) || 0 = 1
PORTB &= 0b11111011;
outputs logic 0 on Pin 2 at Port B, leaving the other pins in whatever state,
because (0) & 1 = 0 and (1) & 1 = 1
_delay_ms(1250);
, which is similar to the delay(ms)
function in the Arduino-C.
#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB = 0b00000100; //Configured Pin 2 at Port B as Output
PORTA = 0b10000000; //Pull-up Pin 7 at Port A.
while (1)
{
if (!(PINA & (0b10000000)))
{
// Output logic 1 on Pin 2 at Port B
PORTB |= 0b00000100;
_delay_ms(1250);
// Output logic 0 on Pin 2 at Port B
PORTB &= 0b11111011;
_delay_ms(1250);
}
}
}
iArduino Interpreter
Downloads