User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Gertboard AVR Programming Counter.ino Demo

Fri May 27, 2016 8:08 pm

The following sketch expands on the standard blink concept including the
basics of LED pin wiggling, button input using the Gertboard button paradigm,
and including a serial comm interface for monitoring the process; as well,
giving the AVR commands (which affect the AVR coding!)
Gertboard_demo.jpg
Gertboard Counter Demo Layout
Gertboard_demo.jpg (48.83 KiB) Viewed 2474 times
In the pic above, I am powering the Gertboard from the PI 5v (pin2) and ground
(pin39); by piggy-backing on the 5v fan pin connectors.

The AVR JTAG connectors are connected to the PI SPI pins at the center of the
GPIO port (GP8, GP9, GP10, GP11).

I'm running the AVR outputs (13, 12, 11, 10) off-board because I ran out of
FF connectors! If I'd had enough connectors I might have used the Gertboard
LEDs...

Gertboard buttons 1 and 2 are on the red and yellow cable at the center of the
board and connect to AVR pins 2 and 3 respectively. I have the output jumpers
attached at channel 1 and 2 (optionally) so I get a visual indicator on my
button presses (for debugging).

The green and purple cable at the center of the board is the serial cable running
to the PI GPIO14 and GPIO15 pins, to allow serial comm interface with the AVR.

The following code is my counter.ino sketch coding just for fun
(and if anyone else wants to screw around with it that's good too).

Code: Select all

/*
  Counter.ino
  
  4 bit binary counter with serial interface

  Mark H. Harris
  5-29-2016
  v0.02j
  
 */
int NOCHAR= -1;
int ESC= 27;
int False=0;
int True=1;
int count=0;   // AVR cycle counter
int button1=2;    // resets cycle counter
int button2=3;    // reverses high-order low-order LED counter
int button3=4;    // sets AVR in sleep mode
char keyin;    // serial command character input
int pins[4] = {13, 12, 11, 10};
int REV[4] = {1, 2, 4, 8};    // pin 10 high-order
int FWD[4] = {8, 4, 2, 1};    // pin 13 high-order
int* FWDREV = FWD;    // bin_display() digits
int swap_flag = False;    // high-order low-order reversed
int button1_flag=False;    // count reset request pending
int button2_flag=False;    // swap request pending
int button3_flag=False;    // sleep mode request pending
int button4_flag=False;    // wiggle mode request pending
int button5_flag=False;    // flash mode request pending
int button6_flag=False;    // scanner mode request pending
int button7_flag=False;    // strobe mode request pending
int button8_flag=False;    // license display request pending
int button9_flag=False;    // help commands menu request pending

void setup() {                
  int i = 0;
  for (i=0; i<=3; i++) {
     pinMode(pins[i], OUTPUT);
  }
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  Serial.begin(9600);
  digitalWrite(button1, HIGH);    // button pullup
  digitalWrite(button2, HIGH);    // button pullup
  digitalWrite(button3, HIGH);    // button pullup
}

void loop() {
   int i=0;
   int j=0;
   button1_flag=False;
   button2_flag=False;
   for (i=0; i<=15; i++) {
     bin_display(i, pins, FWDREV);   // LED counter display
     keyin=Serial.read();    // request commands serially
     if (keyin=='h') {   // page 1 help commands menu
         keyin=help_menu(pins, FWDREV);
         button9_flag=True;
     }
     if (keyin=='h') {   // page 2 help commands menu
         keyin=help_menu_2(pins, FWDREV);
         button9_flag=True;
     }
     if (keyin=='l') {
         keyin=dsp_license(pins, FWDREV);
         button8_flag=True;
     }
     if (!digitalRead(button1) && !button1_flag) {
         Serial.println("AVR cycle Counter reset button");
         button1_flag=True;
     }
     if (!digitalRead(button2) && !button2_flag) {
         Serial.println("AVR orientation swap button");
         button2_flag=True;
     }
     if (keyin=='q' || keyin=='Q') {
         Serial.println("AVR sleep_mode request");
         button3_flag=True;
     }
     if (keyin=='w' || keyin=='W') {
         Serial.println("AVR wiggle mode request");
         button4_flag=True;
     }
     if (keyin=='f' || keyin=='F') {
         Serial.println("AVR flash mode request");
         button5_flag=True;
     }
     if (keyin=='z' || keyin=='Z') {
         Serial.println("AVR scanner mode request");
         button6_flag=True;
     }
     if (keyin=='b' || keyin=='B') {
         Serial.println("AVR strobe mode request");
         button7_flag=True;
     }

     delay(198);
     if (button8_flag || button9_flag)
         break;
   }
   bin_display(0x0, pins, FWDREV);
   delay(770);
   for (i=0; i<=7; i++) {
      keyin=Serial.read();    // process pending requests
      if (button3_flag) {
          sleep_mode(pins);
          button3_flag=False;
      }
      if (button4_flag) {
          wiggle(pins, FWDREV);
          button4_flag=False;
      }
      if (button5_flag) {
          flash(pins, FWDREV);
          button5_flag=False;
      }
      if (button6_flag) {
          scanner(pins, FWDREV);
          button6_flag=False;
      }
      if (button7_flag) {
          strobe(pins, FWDREV);
          button7_flag=False;
      }
      
      bin_display(0xa, pins, FWDREV);
      delay(128);
      bin_display(0x5, pins, FWDREV);
      delay(128);
      if (keyin=='r' || button1_flag) {
         Serial.println("AVR cycle counter reset command");
         count=0;
         button1_flag=False;
      }
      if (keyin=='s' || button2_flag) {
          Serial.println("AVR binary orientation swap command");
          button2_flag=False;
          if (swap_flag) {
              FWDREV = FWD;
              swap_flag = False;
          }
          else {
              FWDREV = REV;
              swap_flag = True;
          }
          if (FWDREV==FWD) {
              for (j=0; j<=3; j++) {
                  Serial.print(pins[j]);
                  Serial.print(", ");
              }
              Serial.println();
          }
          else {
              for (j=3; j>=0; j--) {
                  Serial.print(pins[j]);
                  Serial.print(", ");
              }
              Serial.println();            
          }
      }
   }
   count+=1;
   Serial.print("AVR cycle counter ");
   Serial.println(count);
   button1_flag=False;
   button2_flag=False;
   button8_flag=False;
   button9_flag=False;
   if (!digitalRead(button3))
       sleep_mode(pins);
}

// binary LED display function
void bin_display(int val, int pins[], int digits[]) {
  int n=0;
  for (n=0; n<=3; n++) {
    if (val & digits[n])
        digitalWrite(pins[n], HIGH);
    else 
        digitalWrite(pins[n], LOW);
  }
}

void sleep_mode(int pins[]) {
   int keyin;
   int i;
   for (i=0; i<=3; i++) {
      digitalWrite(pins[i], LOW);
   }
   while (True) {
      for (i=7; i<=245; i++) {
         analogWrite(10, i);
         delay(4);
      }
      keyin = Serial.read();      
      if (keyin=='x' || keyin==ESC)
          break;
      if (!digitalRead(button1))
          wiggle(pins, FWD);
      if (!digitalRead(button2))
          scanner(pins, FWD);
      for (i=245; i>=7; i--) {
         analogWrite(10, i);
         delay(4);
      }          
      keyin = Serial.read();
      if (keyin=='x' || keyin==ESC || !digitalRead(button3))
          break;    
      delay(70);
      if (!digitalRead(button1))
          flash(pins, FWD);
      if (!digitalRead(button2))
          strobe(pins, FWD);
   }
}

void wiggle(int pins[], int digits[]) {
   int keyin;
   while (True) {
      bin_display(0xc, pins, digits);
      delay(127);
      bin_display(0x6, pins, digits);
      delay(127);
      bin_display(0x3, pins, digits);
      delay(127);
      bin_display(0x6, pins, digits);
      delay(120);
      keyin = Serial.read();
      if (keyin=='x' || keyin==ESC || !digitalRead(button1))
          break;      
   }
   bin_display(0x0, pins, digits);
}

void flash(int pins[], int digits[]) {
   int keyin;
   while (True) {
      bin_display(0xf, pins, digits);
      delay(256);
      bin_display(0x0, pins, digits);
      delay(250);
      keyin = Serial.read();
      if (keyin=='x' || keyin==ESC || !digitalRead(button1))
          break;      
   }
   bin_display(0x0, pins, digits);
}

void scanner(int pins[], int digits[]) {
   int keyin;
   int t_delay=128;
   while (True) {
      bin_display(0x8, pins, digits);
      delay(t_delay);
      bin_display(0x4, pins, digits);
      delay(t_delay);
      bin_display(0x2, pins, digits);
      delay(t_delay);
      bin_display(0x1, pins, digits);
      delay(t_delay);
      bin_display(0x2, pins, digits);
      delay(t_delay);
      bin_display(0x4, pins, digits);
      delay(t_delay-7);
      keyin = Serial.read();
      if (keyin=='x' || keyin==ESC || !digitalRead(button1))
          break;      
   }
   bin_display(0x0, pins, digits);
}

void strobe(int pins[], int digits[]) {
   int keyin;
   while (True) {
      bin_display(0x8, pins, digits);
      delay(47);
      bin_display(0x4, pins, digits);
      delay(47);
      bin_display(0x2, pins, digits);
      delay(47);
      bin_display(0x1, pins, digits);
      delay(47);
      bin_display(0x0, pins, digits);
      delay(27);
      keyin = Serial.read();
      if (keyin=='x' || keyin==ESC || !digitalRead(button1))
          break;      
   }
   bin_display(0x0, pins, digits);
}

int help_menu(int pins[], int digits[]) {
   int i;
   char keyin;
   bin_display(0x0, pins, digits);
   for (i=0; i<=24; i++) {
      Serial.println();
   }
   Serial.println("       ***********************************************");
   Serial.println("       **            Commands Help Menu             **");
   Serial.println("       ***********************************************");
   Serial.println("       **  'b' -- strobe                            **");
   Serial.println("       **  'w' -- wiggle                            **");
   Serial.println("       **  'z' -- scanner                           **");
   Serial.println("       **  'f' -- flasher                           **");
   Serial.println("       **  'h' -- (help menu page 2)                **");
   Serial.println("       **  'l' -- license                           **");
   Serial.println("       **  'q' -- quiescense sleep                  **");
   Serial.println("       **  'x' -- exit to counter                   **");
   Serial.println("       ***********************************************");
   for (i=0; i<=7; i++) {
      Serial.println();
   }
   while (True) {
      if (int(keyin=Serial.read())!= NOCHAR)
          break;
      delay(256);
   }
   for (i=0; i<=24; i++) {
      Serial.println();
   }
   return keyin;
}

int help_menu_2(int pins[], int digits[]) {
   int i;
   char keyin;
   bin_display(0x0, pins, digits);
   for (i=0; i<=24; i++) {
      Serial.println();
   }
   Serial.println("       ***********************************************");
   Serial.println("       **         Commands Help Information         **");
   Serial.println("       ***********************************************");
   Serial.println("       **    (2) LED Flasher Command Mode           **");
   Serial.println("       **                                           **");
   Serial.println("       **    'r' -- AVR cycle counter reset         **");
   Serial.println("       **    's' -- AVR binary high-low order swap  **");
   Serial.println("       **                                           **");
   Serial.println("       **                                           **");
   Serial.println("       **             (press any key)               **");
   Serial.println("       **                                           **");
   Serial.println("       ***********************************************");
   for (i=0; i<=7; i++) {
      Serial.println();
   }
   while (True) {
      if (int(keyin=Serial.read())!= NOCHAR)
          break;
      delay(256);
   }
   for (i=0; i<=24; i++) {
      Serial.println();
   }
   return keyin;
}

int dsp_license(int pins[], int digits[]) {
   int i;
   char keyin;
   bin_display(0x0, pins, digits);
   for (i=0; i<=24; i++) {
      Serial.println();
   }
   Serial.println("       ***********************************************");
   Serial.println("       **              Counter License              **");
   Serial.println("       ***********************************************");
   Serial.println("       **                                           **");
   Serial.println("       **    Mark H. Harris                         **");
   Serial.println("       **    v.02j                                  **");
   Serial.println("       **    05-28-2016                             **");
   Serial.println("       **                                           **");
   Serial.println("       **    GPLv3 licesne                          **");
   Serial.println("       **                                           **");
   Serial.println("       **                (press any key)            **");
   Serial.println("       **                                           **");
   Serial.println("       ***********************************************");
   for (i=0; i<=7; i++) {
      Serial.println();
   }
   while (True) {
      if (int(keyin=Serial.read())!= NOCHAR)
          break;
      delay(256);
   }
   for (i=0; i<=24; i++) {
      Serial.println();
   }
   return keyin;
}
The sketch loop() has two phases... 1) the four LEDs blink is binary succession
from 0x0-0xf (the high-low order is selected with serial console command or
button press); and 2) the four LEDs will wiggle during which time
the AVR is in serial command mode.

Reset can be selected during counter mode while the LEDs are in binary
succession with button 1. Button 2 will reverse the high-low order blinking
of the binary LED display.

During binary LED display counting the following serial commands are accepted:

'h' keypress -- 'hello, world'
'r' keypress -- AVR cycle counter reset request
'l' keypress -- 'LED counter = <current counter>'
's' keypress -- AVR LED counter high-low order swap request

WARNING: For what its worth, while this was running I popped the J7 3v3
jumper off the Gertboard to make the input switch connections. Doing so
created some kind or surge on the 5v current and the poly fuse on the
PI tripped! The red light went out, and although the PI did not crash
(unbelievably) the 5v dropped to 4.18 volts. This returned to normal
the following day, after the poly fuse healed.

NOTE: This board is fun to play with; and I think highly useful. I am indeed
thankful to Gert van Loo for developement of the board, and for Gordon @ Drogon
for the software updates to make the Arduino IDE work with the PI and the
Gertboard (very nice piece of engineering, to both you guys-- you rock!)
Last edited by MarkHaysHarris777 on Mon May 30, 2016 3:50 am, edited 3 times in total.
marcus
:ugeek:

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: Gertboard AVR Programming Counter.ino Demo

Sat May 28, 2016 9:01 am

MarkHaysHarris777 wrote: 'h' keypress -- 'hello, world'
'r' keypress -- AVR cycle counter reset request
'l' keypress -- 'LED counter = <current counter>'
's' keypress -- AVR LED counter high-low order swap request
I modified the Counter.ino demo code to allow for sub-command loops(), which are controlled via serial interface character commands during the 'counter' loop phase. The complete list is below:

'q' keypress -- quiescence 'sleep' mode request
'w' keypress -- wiggle mode request
'f' keypress -- flash mode request
'z' keypress -- scanner mode request
'b' keypress -- strobe mode request

'x' exit sub-command loops

While the Counter is in the 'counter' loop() phase the above command characters from the serial console will cause the main loop() to enter a sub-command loop until the exit 'x' character is sent.

The quiescence sleep_mode() uses PWM (analogWrite) to slowly pulse pin10 while everything else comes to a halt. Unlike the PI (which only has one PWM pin) the AVR has six PWM pins, all under control of the PI indirectly.
marcus
:ugeek:

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: Gertboard AVR Programming Counter.ino Demo

Sat May 28, 2016 8:06 pm

Edit: OP updated the code section (v.02h)

I added serial interface command menus, help menu, and license menu. At this point I am very interested in playing around with serial commands and feedback over twisted pair. The IoT idea I'm working on is metrics and control being handled by the micro-controller, whilst the PI is free to handle the analytics. I'm going to be experimenting with creating a Atmega328P control board (similar to the Arduino Uno but without all the cruft... just the 328P, oscillator, and pin headers). I'm planning to communicate with the 328P boards via twisted pair; the 328P will take the measurements, run the servos, click the relays -- whilst the PI gives high-level commands via serial interface, and handling all analytics from feedback it receives from the 328P.

In the v.02h demo code above the 'h' key (which was the dummy hello, world command) now pulls up the serial command help menu, while the 'l' key displays the license information. This works very well over short distances... wondering how long my twisted pair might be able to go without amps, modem, &c.

PS These 363 lines of code compile into just over 7Kb object, or about 1/4 the 328P storage capacity... its amazing how much can be done with such a small space; and, I haven't really been trying to squeeze or optimize.
marcus
:ugeek:

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: Gertboard AVR Programming Counter.ino Demo

Mon May 30, 2016 4:16 am

edit: OP updated code section v.02j {final}

The last phase of this AVR programming experiment was to provide dual controls (serial interface, & full button interface). I added button3 and I redesigned the sleep_mode to be an intermediate command interface; button3 enters and exits the sleep_mode command interface.

Once in the command interface (pwm LED pulsates slowly) buttons 1 & 2 are redefined to select one of the four light patterns manually at either end of the pulsating cycle: H-igh and L-ow:

button1 L-ow : flasher
button1 H-igh: 2 LED scanner
button2 L-ow: strobe
button2 H-gh: 1 LED scanner

Gertboard Notes:

I have had a fun time testing and programming the Gertboard! (fantastic electronics board)

I have a couple of critical comments based on my experiences with the board:

1) The manual and board should be updated for the PI3B; rather than designing the board to plug-in, ribbon cable should be provided for between Gert and PI, with the Gert headers vertical off the top of the board. A programming cable should be provided for sclk, mosi, miso, and SS-reset so that individual jumpers are not required. Two jumper sets should be included by default, and a few more jumper plugs.

2) The manual should be more explicit about the necessity of the 3v3 jumper on J7. It should come installed by default, and be red in color.

3) There should be a reset jumper pin for the AVR . Sometimes when applying power to the Gerboard the AVR does not start. I was able to get around this by briefly jumping pin1 on the AVR to ground. Pin1 has a pullup resistor on it, but there is no reset button, and no reset PIN. icsp header pin(5) is the reset pin!

4) In my opinion the center unused section should employ an MCP23017 on the i2c bus to provide additional IO pins/ as an alternative the MCP23S17 could be provided for the SPI bus/ these would be functional of course, but would provide additional educational opportunities.

5) It is far superior to have the AVR be setup for 3v3; rather than 5v-- unlike the Arduino, the Gertboard AVR is compatible with the RPi-- very nice !

The Gertboard is one of my favorite prototyping boards... next to the PI of course !

marcus

Edit: PS I was able to test my PL2303 to the Gertboard MCTX and MCRX pins from my HP notebook; worked well... very nice !
Last edited by MarkHaysHarris777 on Mon May 30, 2016 10:27 pm, edited 2 times in total.
marcus
:ugeek:

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: Gertboard AVR Programming Counter.ino Demo

Mon May 30, 2016 10:22 pm

Notes: A Gertboard 'reset' button can be jumpered once the icsp AVR programming patch cable has been removed. Running a jumper from icsp header pin(5) rst|dbg|cs over to buffer input B3 (J3) allows the button3 to be the AVR Reset button, similar to the Reset button on the Arduino. Obviously this won't work if the buttons are already in use for something else, or if the icsp header is in use!

It dawned on me that the AVR can be reset under program control too (not just CE0) ; any pin could be setup to momentarily pull the rst icsp header pin(5) to ground to force an AVR 'reboot' of sorts. icsp header pin(5) is connected directly to AVR pin(1) which has a pullup to 3v3.

marcus
marcus
:ugeek:

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: Gertboard AVR Programming Counter.ino Demo

Tue May 31, 2016 12:02 am

Gertboard_duino.jpg
Gertboard -duino (standalone)
Gertboard_duino.jpg (34.57 KiB) Viewed 1956 times
In the pic above I have removed the PI from the picture all-together. In this configuration the Gertboard is being used like an Arduino running stand-alone, being powered from the PL2303 usb plug 3v3 regulator !

Do not try this at home without modifying your PL2303 usb plug!

On the left of the pic see that I have moved the J7 header jumper over to the 5v pins for storage. The J7 is designed so that the Gertboard 3v3 can be routed either from the PI 3v3 line (pin1) or from the PI 5v line (pin2) via the on-board 3v3 regulator supplied by the Gertboard. There is a third option, and that is to remove the jumper J7 all-together and route the 3v3 from the PL2303 usb connector plug via its on-board regulator! ~cool, huh?

On the right of the pic the green Tx line from the PL2303 is plugged into MCRx D0, and the white Rx line from the PL2303 is plugged into the MCTx D1 line of the Gertboard.

Also, in this pic I have button3 configured as an AVR Reset switch... tied to avr pin(1) via the icsp header pin(5) rst. (yellow jumper cable)

marcus
marcus
:ugeek:

Return to “HATs and other add-ons”