PRI: first experience

At the moment of time I had a raspberry Pi arrived from China and really wanted to put my hands on it.

Initially I installed the Raspbian linux on it, but ironically enough I struggled with Chinese memory card a lot and all resolved when I finally bought the well-known in the store.

So what I wanted to do: my adsl modem which I had got for free had some freezes which fixed after the reboot. With time it evolved to each day couple reboots routine.

Solution in mind: to ping some known website one time per n minutes, and, if it is not – make a reboot.

That fact that my PRi stands next to the modem was also in favor of the solution.

Initially, I even thought that I could use the supply from the modem for RPi, but then decided that it doesn’t look nice and practical.

So, we would need to gain the input-output ports control somehow. I used to code in C, so the most convenient tool in C what I found was wiringPi.

This website has quite good theory descriptions and examples of work, just I was puzzled by their pinout:

the RPi pinout

that’s all we need, we need to compile your new source and launch it from root:

gcc -Wall -o execfilename cfilename.c -lwiringPi
sudo ./execfiname

OK, now we know how to control IO, now lets do the website checker. After some websearch I mad a conclusion that function “popen” suits me best. This function allow to call linux commands from the code:

#include <stdio.h>
#include "/usr/include/string.h"
#include "/usr/include/stdlib.h"
 
int main ()
{
 
FILE *cmd = popen ( "ping -c 4 google.com", "r" ); //ping ya.ru 4 раза
char *s = malloc ( sizeof ( char ) * 200 );
while ( 1 )
{
  fgets ( s, sizeof ( char )*200, cmd );
  printf ( "%s", s);//show outcome
  if ( strstr ( s, "icmp_rec" ) != 0 )    //проверяем есть ли нужная инфа
                      break;
}
 
pclose ( cmd );
return 0;
}

That was easy, now a bit of the hardware.

Also quite easy, a transistor which controls the relay which controls the power 🙂

I also added the software watchdog with the 60s period, if it reached one minute and has not been reseted, then we have a frozen program and we need to reset. To work with timers I used the dev/time.h library.

For instance, let me try to ping non-existing website and if we wont be able to reach the response for 5 seconds, we are gonna to reset our mode.

#include <stdio.h>
#include "/usr/include/string.h"
#include "/usr/include/stdlib.h"
#include <sys/time.h>
#include <wiringPi.h>
 
int main ()
{
wiringPiSetup();        //Init wiringPi
pinMode (0, OUTPUT);    //GPIO 0 на выход
digitalWrite (0, LOW);  //и в 0 его сразу
double t1, t2;
unsigned char flag = 0;
struct timeval tim;
gettimeofday(&tim, NULL);
t1=tim.tv_sec+(tim.tv_usec/1000000.0);  //Время старта в секундах
FILE *cmd = popen ( "ping -c 4 razdvatridvaodin.com", "r" ); 
char *s = malloc ( sizeof ( char ) * 200 );
do
 {
  fgets ( s, sizeof ( char )*200, cmd );
  printf ( "%s", s);//show outcome
  gettimeofday(&tim, NULL);
  t2 = tim.tv_sec+(tim.tv_usec/1000000.0);  //Текущее время работы в секундах
  if ( strstr ( s, "ms" ) != 0 )    //проверяем допинговались ли мы куда-нибудь вообще, если да то прерываем цикл
   {
     flag = 1;
     break;
   }
 }while((t2-t1)<5);        //Если висим слишком долго то пора делать ребут
 
if (!flag)                 //Обрабатываем отсутствие коннекта
{
  digitalWrite (0, HIGH);
  delay(1000);
  delay(1000);
  digitalWrite (0, LOW);
}
 
pclose ( cmd );
return 0;
}

a result:

Works!

The final code:

#include <stdio.h>
#include "/usr/include/string.h"
#include "/usr/include/stdlib.h"
#include <sys/time.h>
#include <wiringPi.h>
 
int main ()
{
wiringPiSetup();        //Init wiringPi
pinMode (0, OUTPUT);    //0 пин на выход
digitalWrite (0, LOW);  //пока не трогаем его
double t1, t2;
unsigned char flag = 0;
struct timeval tim;
gettimeofday(&tim, NULL);
t1=tim.tv_sec+(tim.tv_usec/1000000.0);  //Время старта в секундах
FILE *cmd = popen ( "ping -c 4 google.com", "r" ); //ping google.com 4 раза
char *s = malloc ( sizeof ( char ) * 200 );
do
{
   fgets ( s, sizeof ( char )*200, cmd );
   printf ( "%s", s);//show outcome
   gettimeofday(&tim, NULL);
   t2 = tim.tv_sec+(tim.tv_usec/1000000.0);  //Текущее время работы в секундах
   if ( strstr ( s, "ms" ) != 0 )    //проверяем допинговались ли мы куда-нибудь вообще, если да то прерываем цикл
   {
       flag = 1;                     //устанавливаем флаг
       break;                        //выходим из цикла
   }
}while((t2-t1)<60);        //Если висим слишком долго то пора делать ребут
 
if (!flag)                 //Обрабатываем отсутствие коннекта
{
  digitalWrite (0, HIGH);
  delay(1000);
  delay(1000);
  digitalWrite (0, LOW);
}
 
pclose ( cmd );
return 0;
}

Great, we have some code, which even works, now we need to schedule the launching of this program each n minutes. Linus usually uses cron service, the help related to this service could be found in many places and raspberry PI website one of them. And that what I would usually do, but here is the information that advanced users should not use it, not sure why, but let me pretend that I am an advanced user.

To check how it works I made a simple code which just writes a current time to the file:

#include <time.h>
#include <stdio.h>
 
int main( void )
{
FILE * fp;
fp = fopen ("/home/pi/Buf/file.txt", "a+");
time_t t;
time(&t);
fprintf( fp, "The time is %s\n", ctime( &t) );
 
fclose(fp);
 
return 0;
 
}

Compiling the code, naming it TimeIs and going to /etc/cron.d, creating a file mycronjob there with a next context:

*/1 * * * * root /home/pi/Buf/./TimeIs

Which means that the function is going to be launched each minute, checking the result:

The time is Sun Jul 20 18:38:01 2014
 
The time is Sun Jul 20 18:39:02 2014
 
The time is Sun Jul 20 18:40:01 2014
 
The time is Sun Jul 20 18:41:01 2014
 
The time is Sun Jul 20 18:42:01 2014
 
The time is Sun Jul 20 18:43:01 2014

At this moment of time I decided that I also need to have logs:

if (!flag)                 //Обрабатываем отсутствие коннекта
{
digitalWrite (0, HIGH);
delay(1000);
delay(1000);
digitalWrite (0, LOW);
 
fprintf( fp, "Test of connection failed at %s\n", ctime( &t) );
} else
fprintf( fp, "Test of connection passed at %s\n", ctime( &t) );

Settled the cron time to be 10 min and we are ready. Here also some messy photos of the hardware:

The sources

Leave a Reply

Your email address will not be published.