6 ways to blink a led with a Pinguino

Here are 6 ways to blink the built-in LED on your Pinguino board :

void setup()
{
TRISAbits.TRISA4 = OUTPUT;
}

void loop()
{
LATAbits.LATA4 = LOW;
delay(50);
LATAbits.LATA4 = HIGH;
delay(500);
}
Example 1 : with PIC registers
void setup()
{
pinMode(USERLED, OUTPUT);
}

void loop()
{
digitalWrite(USERLED, LOW);
delay(500);
digitalWrite(USERLED, HIGH);
delay(500);
}
Example 2 : the Arduino way
void setup()
{
pinMode(USERLED, OUTPUT);
}

void loop()
{
toggle(USERLED);
delay(500);
}
Example 3 : even simpler ?
void myBlink() { toggle(USERLED); }

void setup()
{
pinMode(USERLED, OUTPUT);
// Use Timer0 to toggle the USERLED every 500 ms
OnTimer0(myBlink, INT_MILLISEC, 500);
}

void loop()
{
}
Example 4 : using an interrupt
void setup()
{
pinMode(USERLED, OUTPUT);
// Enable Watchdog Timer
// Watchdog is driven by the Internal Oscillator (8MHz)
// Nominal period of Watchdog is 4ms
// Watchdog postscaler is set to 1:32768 by config. bits
// Watchdog timer will overload after 32768*4ms = 135sec = 2.25min
System.watchdog();
}

void loop()
{
System.clearWatchdog(); // clear watchdog timer
// Enter Sleep Mode
System.sleep(); // wait for watchdog timer overload
// Back to Run Mode
toggle(USERLED); // toggle the led
}
Example 5 : using the watchdog
blink.gpde
void setup()
{
pinMode(USERLED, OUTPUT);
}

void loop()
{
toggle(USERLED);
delay(500);
}
Example 6 : using the Pinguino Graphical Language

#Pinguino has now it’s own (DIY) debugger

Most Pinguino boards does not have displays so debugging programs is not as easy as it could be in a real PC environment. There are also some situations where you cannot simply add breakpoints to you code and view them in your IDE because you cannot stop the program flow (real time decoding of a data stream cannot be stopped to see what happens at a certain point of the code).

One simple thing that could be done is to put along the program flow some two-digit codes as a flag evidence and pass them to an external device that would display them. So you will know where you are in the program flow and what branch is being executed. This was the original idea behind Fabio’s project.

In his article Fabio shows you the complete development and building from scratch of his tiny debugger. The aim of this project is to explain to students and hobbyists a working method that can lead from ideas to a real working device.

How to use interrupt on Pinguino32

Pinguino32 doesn’t support interrupt routines without writing a code in an assembler file. We decided to open interrupt to everybody. To do this, we used some of the special attribute directive of GCC. Now you can deal with Interrupt without assembler.

This example show how to use the Timer 1 to increment a counter.

// Using interrupt with Pinguino32
// Jean-Pierre MANDON 2011

#include <interrupt.c>

unsigned int counter=0;


void ISR_wrapper_vector_4(void) __attribute__ ((section (".vector_4")));
// Put the ISR_wrapper in the good place

void ISR_wrapper_vector_4(void) { Tmr1Interrupt(); }
// ISR_wrapper will call the Tmr1Interrupt()

void Tmr1Interrupt(void) __attribute__ ((interrupt));
// Tmr1Interrupt is declared as an interrupt routine

// define here the code to execute when an interrupt occure
void Tmr1Interrupt(void)
{
if (IFS0bits.T1IF)		// Timer Interrupt flag
	{
	TMR1=0;			// reset the timer register
	IFS0CLR=0x10;		// Clear the timer interrupt flag
	counter++;		// increment the counter
	}
}

// configure timer 1 
void init_timer1(void)
{
IntConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);	// interrupt mode (interrupt.c)
T1CON=0;		// reset timer 1 configuration
TMR1=0;			// reset timer 1 counter register
PR1=0x9999;		// define the preload register
IPC1SET=0x7;		// select interrupt priority and sub-priority
IFS0CLR=0x10;		// clear interrupt flag
IEC0SET=0x10;		// enable timer 1 interrupt
T1CONSET=0x8010;	// start timer 1 and set prescaler
}

void setup()
{
init_timer1();
}

void loop()
{
CDC.printf("%d\n\r",counter);	// counter is incremented at each timer 1 overflow
delay(1);
}

Be careful, some interruption are already used by Pinguino32. Vector_8 (timer 2) is used by the function millis(). vector_24 (Serial1 interrupt) and vector_32 (Serial2 interrupt) are used by the serial module. vector_35 ( RTCC ) is used by the real time clock module.
All the test have been made with a PIC32-PINGUINO-OTG board and Linux IDE.

8 PWM output on Pinguino !!

This is an interrupt code example. It show how to build 8 PWM output on pin 0 to 7 with the timer 1. The PWM frequency is about 400 Hz. With the 2 analogWrite output, you can now drive 10 PWM outputs and this code can be adapted to drive 16 PWM outputs.
Applications are motors, lights and others analogic outputs.

// How to use interrupt on Pinguino
// add 8 analog outputs ( PWM ) to your Pinguino
// can be extended to 16
// Jean-Pierre MANDON 2009

08/04/2009
When copied to the blog, this file is corrupted.
You can download the source here.

How to use Interrupt with Pinguino……

With beta 5 you can use interrupt in a Pinguino program. This is a simple example to blink a led with timer 1. Nothing to do in the main loop because level of the led is changed by the interrupt routine.

// How to use interrupt on Pinguino
// simple example blink a led with timer 1
// led is connected on output 0
// Jean-Pierre Mandon 2009

void UserInterrupt()
{
// timer 1 interrupt flag in register PIR1
if (PIR1bits.TMR1IF)
{
// reset interrupt flag
PIR1bits.TMR1IF=0;
// reverse state of pin 0 ( blink )
digitalWrite(0,digitalRead(0)^1);
}
}

void setup()
{
// led is connected on output 0
pinMode(0,OUTPUT);
// timer 1 configuration
// you can write T1CON=0xB1; or
// timer1 register is 16 bits
T1CONbits.RD16=1;
// clock source for timer 1 is derived from clock
T1CONbits.T1RUN=0;
// prescale value 1/8
T1CONbits.T1CKPS1=1;
T1CONbits.T1CKPS0=1;
// timer 1 oscillator is shut off ( internal clock )
T1CONbits.T1OSCEN=0;
// T1SYNC is not used ( internal clock )
// timer clock is internal clock ( Fosc/4 )
T1CONbits.TMR1CS=0;
// timer 1 is On
T1CONbits.TMR1ON=1;
// FOSC is 48 Mhz => Internal clock = 48 Mhz / 4 = 12 Mhz
// clock period is 83 nS
// prescale for timer 1 is 8 => clock period for timer 1 is 667 nS
// timer 1 is incremented every 667 nS
// timer 1 is a 16 bits register, it will overflow every 667nS*65536 = 43.6 mS
// when timer 1 overflow it generate an interrupt
// Interrupt configuration
// enable interrupt for timer1 in register PIE1
PIE1bits.TMR1IE=1;
// Here you can write INTCON|=0xC0; or
// enable peripheral interrupt
INTCONbits.PEIE=1;
// global enable interrupt
INTCONbits.GIE=1;
// now an interrupt will be generated by timer1 every 43,6 mS
}

void loop()
{
// nothing to do in the main loop 🙂
}

Pinguino with CodeBlocks…………

Pinguino can be used with CodeBlocks. To do this, you need to install SDCC and GPUTILS. CodeBlocks recognize if SDCC is installed.
First you must download the CodeBlocks model for Pinguino.
Then you have to configure CodeBlocks to work with SDCC.

Create a new empty project in the same folder than the CodeBlocks model,
Go to the Settings menu/Compiler and debugger and choose SDCC in the Selected compiler panel,
Click the compiler settings tab and Compiler flags tab and select:

  • Be verbose
  • [CPU] PIC 16 bits
  • ouput intel hex

Select the Other Options panel and type:

  • –optimize-goto –denable-peeps –obanksel=9 –opt-code-size –optimize-cmp –optimize-df

Then all the general settings for the compiler are OK. You must now configure the specific options for Pinguino.
Select the Project/Build Options menu,
Click on the Compiler Settings tab and Other Options tab,
type -p18f2550 in the field.
Click now on the Linker Settings panel.
In the Other Linker Options field, type:
–no-crt -Wl-s18f2550.lkr,-m
In the Link Libraries field, click on add and select this files:
libpuf.lib wich is in the project folder,
libc18f.lib wich is in the /usr/share/sdcc/lib/pic16 folder ( Linux )
libio18f2550.lib
wich is in the /usr/share/sdcc/lib/pic16 folder ( Linux )

Now you can click on the Build button and an hex file should be generated.
All the code must be written in the application_main() in main.c

To upload the code to the PIC, you can use the Python downloader wich can be downloaded here.

I hope to propose some models of applications.