text:
Arduino memory issue with old HP HDSP-2000 display chips

I'm running into memory issues with an Arduino Nano driving some old HDSP-2000/HDSP-2011 chips.
I cannot seem to get the ASCII 5x7 array into PROGMEM and have it read properly. It's so low on memory that I set up a second Arduino to send char[] strings through I2C to keep the Nano from locking up. This sort of worked to my advantage that I can multi-task and I'll probably keep it that way but it still keeps locking up or spitting gibberish.
The display Arduino is constantly bit-banging the displays - multiplexed with two 14-bit (acts as one 28-bit) Serial in / parallel out shift registers and and 5 column drivers. All displays use 5 common anode + columns, which have to be pulse timed with the registers.
#include <Wire.h>

//*** HDSP2011 Display Demo
//*** ASCII-DEMO
//*** phuinink@gmail.com
//*** Paul Huinink has a webpage on displays www.huinink.info and specifically HDSP200X series displays www.spagmon.com
//*** Modified December-2013 by Patrick Hickey: added HP HDSP single digit display and RGB LED
//*** Patrick Hickey ph@nipht.com

//modified 3/2018 by Brandon McRee - removed support for LED and single digit HDSP DISPLAY

//figure out latch pin

// an array of 5 bytes per ASCII
// 5 bytes cause 5 columns
// 7 bits per column (no LSB)

const byte ascii_5x7[] = {    //when I put this in PROGMEM i get gibberish, without it the SRAM is 87% full...
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xF2, 0x00, 0x00,// !
    0x00, 0xE0, 0x00, 0xE0, 0x00,// "
    0x28, 0xFE, 0x28, 0xFE, 0x28,// #
    0x24, 0x54, 0xFE, 0x54, 0x48,// $
    0xC4, 0xC8, 0x10, 0x26, 0x46,// %
    0x6C, 0x92, 0xAA, 0x44, 0x0A,// &
    0x00, 0xA0, 0xC0, 0x00, 0x00,// 39
    0x00, 0x38, 0x44, 0x82, 0x00,// 40
    0x00, 0x82, 0x44, 0x38, 0x00,// 41
    0x28, 0x10, 0x7C, 0x10, 0x28,// *
    0x10, 0x10, 0x7C, 0x10, 0x10,
    0x00, 0x0A, 0x0C, 0x00, 0x00,
    0x10, 0x10, 0x10, 0x10, 0x10,
    0x00, 0x06, 0x06, 0x00, 0x00,
    0x04, 0x08, 0x10, 0x20, 0x40,
    0x7C, 0x8A, 0x92, 0xA2, 0x7C,//48 0
    0x00, 0x42, 0xFE, 0x02, 0x00,//49 1
    0x42, 0x86, 0x8A, 0x92, 0x62,//50 2
    0x84, 0x82, 0xA2, 0xD2, 0x8C,
    0x18, 0x28, 0x48, 0xFE, 0x08,
    0xE4, 0xA2, 0xA2, 0xA2, 0x9C,
    0x3C, 0x52, 0x92, 0x92, 0x0C,
    0x80, 0x8E, 0x90, 0xA0, 0xC0,
    0x6C, 0x92, 0x92, 0x92, 0x6C,
    0x60, 0x92, 0x92, 0x94, 0x78,
    0x00, 0x6C, 0x6C, 0x00, 0x00,
    0x00, 0x6A, 0x6C, 0x00, 0x00,
    0x10, 0x28, 0x44, 0x82, 0x00,
    0x28, 0x28, 0x28, 0x28, 0x28,
    0x00, 0x82, 0x44, 0x28, 0x10,
    0x40, 0x80, 0x8A, 0x90, 0x60,
    0x4C, 0x92, 0x9E, 0x82, 0x7C,
    0x7E, 0x88, 0x88, 0x88, 0x7E,//65 A
    0xFE, 0x92, 0x92, 0x92, 0x6C,
    0x7C, 0x82, 0x82, 0x82, 0x44,
    0xFE, 0x82, 0x82, 0x44, 0x38,
    0xFE, 0x92, 0x92, 0x92, 0x82,
    0xFE, 0x90, 0x90, 0x90, 0x80,// 70
    0x7C, 0x82, 0x92, 0x92, 0x5E,
    0xFE, 0x10, 0x10, 0x10, 0xFE,
    0x00, 0x82, 0xFE, 0x82, 0x00,
    0x04, 0x02, 0x82, 0xFC, 0x80,
    0xFE, 0x10, 0x28, 0x44, 0x82,
    0xFE, 0x02, 0x02, 0x02, 0x02,
    0xFE, 0x40, 0x30, 0x40, 0xFE,
    0xFE, 0x20, 0x10, 0x08, 0xFE,
    0x7C, 0x82, 0x82, 0x82, 0x7C,
    0xFE, 0x90, 0x90, 0x90, 0x60,// P
    0x7C, 0x82, 0x8A, 0x84, 0x7A,
    0xFE, 0x90, 0x98, 0x94, 0x62,
    0x62, 0x92, 0x92, 0x92, 0x8C,
    0x80, 0x80, 0xFE, 0x80, 0x80,
    0xFC, 0x02, 0x02, 0x02, 0xFC,
    0xF8, 0x04, 0x02, 0x04, 0xF8,
    0xFC, 0x02, 0x0C, 0x02, 0xFC,
    0xC6, 0x28, 0x10, 0x28, 0xC6,
    0xE0, 0x10, 0x0E, 0x10, 0xE0,
    0x86, 0x8A, 0x92, 0xA2, 0xC2,
    0x00, 0xFE, 0x82, 0x82, 0x00,
    0x40, 0x20, 0x10, 0x08, 0x04,
    0x00, 0x82, 0x82, 0xFE, 0x00,
    0x20, 0x40, 0x80, 0x40, 0x20,
    0x02, 0x02, 0x02, 0x02, 0x02,
    0x00, 0x80, 0x40, 0x20, 0x00,
    0x04, 0x2A, 0x2A, 0x2A, 0x1E,
    0xFE, 0x12, 0x12, 0x12, 0x0C,
    0x1C, 0x22, 0x22, 0x22, 0x22,
    0x0C, 0x12, 0x12, 0x12, 0xFE,// 100 d
    0x1C, 0x2A, 0x2A, 0x2A, 0x1A,// 101 e
    0x00, 0x10, 0x7E, 0x90, 0x40,
    0x12, 0x2A, 0x2A, 0x2A, 0x3C,
    0xFE, 0x10, 0x10, 0x10, 0x0E,
    0x00, 0x00, 0x5E, 0x00, 0x00,
    0x04, 0x02, 0x02, 0xBC, 0x00,
    0x00, 0xFE, 0x08, 0x14, 0x22,
    0x00, 0x82, 0xFE, 0x02, 0x00,
    0x3E, 0x20, 0x1C, 0x20, 0x3E,
    0x3E, 0x10, 0x20, 0x20, 0x1E,
    0x1C, 0x22, 0x22, 0x22, 0x1C,
    0x3E, 0x28, 0x28, 0x28, 0x10,
    0x10, 0x28, 0x28, 0x28, 0x3E,
    0x3E, 0x10, 0x20, 0x20, 0x10,
    0x12, 0x2A, 0x2A, 0x2A, 0x24,
    0x20, 0x20, 0xFC, 0x22, 0x24,
    0x3C, 0x02, 0x02, 0x02, 0x3C,
    0x38, 0x04, 0x02, 0x04, 0x38,
    0x3C, 0x02, 0x0C, 0x02, 0x3C,// x
    0x22, 0x14, 0x08, 0x14, 0x22,// y
    0x20, 0x12, 0x0C, 0x10, 0x20,// z
    0x22, 0x26, 0x2A, 0x32, 0x22,//123 {
    0x00, 0x10, 0x6C, 0x82, 0x82,//124 |
    0x00, 0x00, 0xEE, 0x00, 0x00,//125 }
    0x82, 0x82, 0x6C, 0x10, 0x00,
    0x20, 0x40, 0x40, 0x40, 0x80,
    0xA8, 0x68, 0x3E, 0x68, 0xA8,
    0xBE, 0x2A, 0x2A, 0x2A, 0xA2,
    0x00, 0x20, 0x50, 0xA0, 0x00,
    0x04, 0x22, 0x7C, 0xA0, 0x40,
    0x84, 0xFC, 0x04, 0x00, 0x20,
    0xFE, 0x02, 0x02, 0x12, 0x02,
    0x1C, 0x22, 0x14, 0x08, 0x36,
    0x4E, 0x3E, 0x60, 0x40, 0x40,
    0x0C, 0x12, 0x52, 0xB2, 0x1C,//136 ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âª
    0x08, 0x1C, 0x2A, 0x2A, 0x2A,
    0xF8, 0x40, 0x40, 0x3C, 0x02,
    0x7C, 0x92, 0x92, 0x7C, 0x00,
    0x42, 0x44, 0x38, 0x04, 0x02,
    0x20, 0x3E, 0x20, 0x3E, 0x22,
    0x10, 0x20, 0x3C, 0x22, 0x20,
    0x18, 0x24, 0x7E, 0x24, 0x18,
    0x1C, 0x22, 0x0C, 0x22, 0x1C,
    0x82, 0xC6, 0xAA, 0x92, 0x82,
    0x3A, 0x46, 0x40, 0x46, 0x3A,
    0x54, 0x54, 0x54, 0x54, 0x54,
    0x44, 0x28, 0x10, 0x28, 0x44,
    0x10, 0x10, 0x54, 0x10, 0x10,
    0x00, 0x70, 0x88, 0x88, 0x70,
    0x60, 0x90, 0x8A, 0x80, 0x40,
    0xFE, 0xFE, 0x92, 0x92, 0x92,
    0x0A, 0x1A, 0x2A, 0x4A, 0x8A,
    0x8A, 0x4A, 0x2A, 0x1A, 0x0A,
    0x28, 0x2C, 0x38, 0x68, 0x28,
    0x04, 0xFE, 0x80, 0x80, 0x80,
    0x4C, 0x92, 0x92, 0x7C, 0x00,//157 ÃƒÆ’Ã†â€™Ãƒâ€¹Ã…â€œ
    0x04, 0x02, 0x7C, 0x80, 0x40,
    0x38, 0x44, 0x38, 0x44, 0x38,
    0xAA, 0x54, 0xAA, 0x54, 0xAA,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xBE, 0x00, 0x00,
    0x38, 0x44, 0xFE, 0x44, 0x00,
    0x12, 0x7E, 0x92, 0x92, 0x42,
    0xBA, 0x44, 0x44, 0x44, 0xBA,
    0xA8, 0x68, 0x3E, 0x68, 0xA8,
    0x00, 0x00, 0xEE, 0x00, 0x00,
    0x50, 0xAA, 0xAA, 0xAA, 0x14,
    0x00, 0x80, 0x00, 0x80, 0x00,
    0x7C, 0xBA, 0xAA, 0xAA, 0x7C,
    0x12, 0xAA, 0xAA, 0xAA, 0x7A,
    0x10, 0x28, 0x54, 0xAA, 0x44,
    0x80, 0x80, 0x80, 0x80, 0xC0,
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x7C, 0xAA, 0xBA, 0x82, 0x7C,
    0x80, 0x80, 0x80, 0x80, 0x80,
    0x00, 0xE0, 0xA0, 0xE0, 0x00,
    0x22, 0x22, 0xFA, 0x22, 0x22,
    0x00, 0x48, 0x98, 0xA8, 0x48,
    0x00, 0x00, 0xA8, 0xA8, 0x70,
    0x00, 0x00, 0x40, 0x80, 0x00,
    0x04, 0xF8, 0x10, 0x10, 0xE0,
    0x60, 0xFE, 0x80, 0xFE, 0x80,
    0x00, 0x00, 0x10, 0x10, 0x00,
    0x08, 0x00, 0x02, 0x04, 0x00,
    0x00, 0x48, 0xF8, 0x08, 0x00,
    0x00, 0xE8, 0xA8, 0xE8, 0x00,
    0x44, 0xAA, 0x54, 0x28, 0x10,
    0xF0, 0x04, 0x0C, 0x14, 0x2E,
    0xF0, 0x00, 0x12, 0x26, 0x1A,
    0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
    0x0C, 0x12, 0xA2, 0x02, 0x04,
    0x1E, 0xA8, 0x68, 0x28, 0x1E,
    0x1E, 0x28, 0x68, 0xA8, 0x1E,
    0x1E, 0xA8, 0xA8, 0xA8, 0x1E,
    0x9E, 0xA8, 0xA8, 0xA8, 0x9E,
    0x9E, 0x28, 0x28, 0x28, 0x9E,
    0x1E, 0x68, 0xA8, 0x68, 0x1E,
    0x7E, 0x90, 0xFE, 0x92, 0x92,
    0x70, 0x8A, 0x8C, 0x88, 0x88,
    0x3E, 0xAA, 0x6A, 0x2A, 0x22,
    0x3E, 0x2A, 0x6A, 0xAA, 0x22,
    0x3E, 0xAA, 0xAA, 0xAA, 0x22,
    0xBE, 0x2A, 0x2A, 0x2A, 0xA2,
    0x00, 0xA2, 0x7E, 0x22, 0x00,
    0x00, 0x22, 0x7E, 0xA2, 0x00,
    0x00, 0xA2, 0xBE, 0xA2, 0x00,
    0x00, 0xA2, 0x3E, 0xA2, 0x00,
    0x10, 0xFE, 0x92, 0x82, 0x7C,
    0xBE, 0x90, 0x88, 0x84, 0xBE,
    0x1C, 0xA2, 0x62, 0x22, 0x1C,
    0x1C, 0x22, 0x62, 0xA2, 0x1C,
    0x1C, 0xA2, 0xA2, 0xA2, 0x1C,
    0x9C, 0xA2, 0xA2, 0xA2, 0x9C,
    0x9C, 0x22, 0x22, 0x22, 0x9C,
    0x44, 0x28, 0x10, 0x28, 0x44,
    0x3A, 0x4C, 0x54, 0x64, 0xB8,
    0x3C, 0x82, 0x42, 0x02, 0x3C,
    0x3C, 0x02, 0x42, 0x82, 0x3C,
    0x3C, 0x82, 0x82, 0x82, 0x3C,
    0xBC, 0x02, 0x02, 0x02, 0xBC,
    0x60, 0x10, 0x4E, 0x90, 0x60,
    0xFE, 0x44, 0x44, 0x44, 0x38,
    0x7E, 0xA4, 0xA4, 0x58, 0x00,
    0x04, 0xAA, 0x6A, 0x2A, 0x1E,
    0x04, 0x2A, 0x6A, 0xAA, 0x1E,
    0x04, 0xAA, 0xAA, 0xAA, 0x1E,
    0x84, 0xAA, 0xAA, 0xAA, 0x9E,
    0x04, 0xAA, 0x2A, 0xAA, 0x1E,
    0x04, 0x6A, 0xAA, 0x6A, 0x1E,
    0x2E, 0x2A, 0x1C, 0x2A, 0x3A,
    0x30, 0x4A, 0x4C, 0x48, 0x00,
    0x1C, 0xAA, 0x6A, 0x2A, 0x1A,
    0x1C, 0x2A, 0x6A, 0xAA, 0x1A,
    0x1C, 0xAA, 0xAA, 0xAA, 0x1A,
    0x1C, 0xAA, 0x2A, 0xAA, 0x1A,
    0x00, 0x80, 0x5E, 0x00, 0x00,
    0x00, 0x00, 0x5E, 0x80, 0x00,
    0x00, 0x40, 0x5E, 0x40, 0x00,
    0x00, 0x40, 0x1E, 0x40, 0x00,
    0x0C, 0x12, 0x52, 0xB2, 0x1C,
    0xBE, 0x90, 0xA0, 0xA0, 0x9E,
    0x0C, 0x92, 0x52, 0x12, 0x0C,
    0x0C, 0x12, 0x52, 0x92, 0x0C,
    0x0C, 0x52, 0x52, 0x52, 0x0C,
    0x4C, 0x52, 0x52, 0x52, 0x4C,
    0x0C, 0x52, 0x12, 0x52, 0x0C,
    0x10, 0x10, 0x10, 0x54, 0x10,
    0x18, 0x26, 0x3C, 0x64, 0x18,
    0x1C, 0x82, 0x42, 0x02, 0x1C,
    0x1C, 0x02, 0x42, 0x82, 0x1C,
    0x1C, 0x42, 0x42, 0x42, 0x1C,
    0x1C, 0x42, 0x02, 0x42, 0x1C,
    0x20, 0x12, 0x4C, 0x90, 0x20,
    0xFE, 0x48, 0x48, 0x30, 0x00,
    0x20, 0x92, 0x0C, 0x90, 0x20,

};

int column[] = {
    8,7,6,5,4}; // change this to other general input/output arduino-pins as you like d8=pin 1
int data = 2;   // change this to other general input/output arduino-pins as you like
int clock = 3;  // change this to other general input/output arduino-pins as you like

int brightness = 2000; // keep high for max visibility. To high will cause flikkering

const int numberOflDisplays = 4; // change this if total number of HDSP200x's is different.

int tekstDat[numberOflDisplays * 4 * 5]; // this is the array that store's what on the displays. 4 digits per display and 5 columns per digit.

unsigned long tijd; // used to trigger events in one of the examples below

char buf[40];
boolean flagRx = false; //allowed to receive if false

//*****************************************************************setup*************************************************************
void setup(){
    //Serial.begin(9600);

    for (int i = 0; i < 5; i++){
        pinMode(column[i], OUTPUT);
    }
    for (int i = 0; i < 5; i++){
        digitalWrite(column[i], LOW);
    }
    pinMode(data, OUTPUT);
    pinMode(clock, OUTPUT);
    digitalWrite(data, LOW);
    digitalWrite(clock, HIGH);
    tijd = millis();

    Wire.begin(8);                // join i2c bus with address #8  >>important<<
    Wire.onReceive(receiveEvent); // register event

}

//***********************************************************************************end setup******************************************************

void loop(){

    char PROGMEM clr[] = "    ";
    char PROGMEM scroll[]  = "1979 TECH CONTROL PANEL by Brandon McRee";
    char PROGMEM scroll2[] = "Remember Stupid... you have to drive this home :)";

    if(flagRx == false){
        delay(10); //needs this delay to be stable
        scrollText(scroll, 8); //scrolling text, speed : second number is var howslow how slow this is a test of fastdraw text (short strings)
        delay(1000);
        //scrollText(scroll2, 10);
        delay(10);
        flagRx = true; // can now recieve
    }
    else{
        writeText(buf);
        for (int i = 0; i< 50; i++) draw(); //does this continuously - display HDSP2011

    }
    /*
            scrollText(scroll3, 10);
            delay(10);

        //short quick text write
        scrollText(hello, 8);
        scrollText(world, 8);
        delay(500);

            delay(5);
        writeText("TEST") ;                   //letters only? special charachters
        for (int i = 0; i< 100; i++) draw();
                delay(5);
        writeText("ABCDEFGHIJKLMNOPQRSTUVWXYZ") ;
        for (int i = 0; i< 70; i++) draw();
                delay(5);
        writeText("1234567890") ;
        for (int i = 0; i< 100; i++) draw();
                delay(5);
        writeText("!@#$%^&*()") ;
        for (int i = 0; i< 50; i++) draw(); //delay??
                delay(5);

        delay(1000);

            */

    writeText(buf);
    for (int i = 0; i< 50; i++) draw(); //does this continuously

}
//****************end of main loop *********************************

void receiveEvent(int howMany) {

    int i;
    for (i=0; i<howMany; i++){
        buf[i] = Wire.read(); //read I2C data (address 8)
    }

    flagRx = true;    // set flag, we received something. will figure out how to clear when

    // while (1 < Wire.available()) { // loop through all but the last

}

//int x = Wire.read();    // receive byte as an integer not used
//Serial.println(x);          // print the integer

void writeDigit(int positie, int ascii){
    for (int i =0; i< 5;i++){
        tekstDat[(numberOflDisplays * 4 - positie) * 5 + i] = ascii_5x7[ascii*5+i];
    }
}

void scrollText(String tekkst, long howSlow){
    int leng = tekkst.length();
    for (int u=-numberOflDisplays*4;u<leng;u++){ // first N digits will be spaces. N = all digits of display. So one screen blank before first character apears.
        for (int v=0; v< numberOflDisplays*4;v++){
            if (( (u+v) >= 0 ) && ((u+v) < leng)){ // separete leading and tailing spaces from actual string
                char oneChar= tekkst.charAt(u+v);
                writeDigit(v+1, oneChar); // write the character of the string
            }
            else{
                writeDigit(v+1, 32); // write ascii-value 32 = a space.
            }
        }
        for (long teller = 0; teller < howSlow; teller++){
            draw();
        }
    }
}

void writeText(String tekst){
    int tl = tekst.length();
    int spacesNeeded = 4 * numberOflDisplays - tl;
    if (spacesNeeded <0){
        tl = 4 * numberOflDisplays;
    }
    else{
        for (int u = 0; u < spacesNeeded; u++){
            tekst.concat(" ");
        }
        tl = 4 * numberOflDisplays;
    }
    char tekst_[tl];
    for (int vv = 0; vv < tl; vv++){
        char tt = tekst.charAt(tl-vv-1);
        for (int i =0; i< 5;i++){
            //tekstDat[vv*5+i] = ascii_5x7[tt*5+i]; //old using SRAM
            //tekstDat[vv*5+i] = (pgm_read_byte(ascii_5x7))[tt*5+i]; //new  try and read from PROGMEM does not compile :/
        }
    }
}

void dot(byte x, byte y, boolean oo){
    if ((x < (numberOflDisplays *4 * 5)) && (y < 7)){
        byte oldByte = tekstDat[x] & (0xFF - (2<<y));
        tekstDat[x] = oldByte | (2<<y);
    }
}

void draw(){
    for (int Kolom = 0; Kolom < 5; Kolom++){ // 5 columns to be strobed
        // pumping in 3 x 4 x 7 bits per one stobe of the column
        for (int displayNo = 0; displayNo < numberOflDisplays; displayNo++){  // number of  displays
            for (int digitNo = 0; digitNo < 4; digitNo++){ // 4 characters per display
                for (int diodeNo = 0; diodeNo < 7; diodeNo++){ // 7 row-elements
                    digitalWrite(clock, HIGH);
                    digitalWrite(data, tekstDat[Kolom + 5*(displayNo*4 + digitNo) ] &(2<<diodeNo)); // magic
                    digitalWrite(clock, LOW);
                }
            }
        }
        digitalWrite(column[Kolom], HIGH);
        delayMicroseconds(brightness);
        digitalWrite(column[Kolom], LOW);
    }
}

“I cannot seem to get the ASCII 5x7 array into PROGMEM and have it read properly.” You should solve this problem, rather than try to work around it. A font definitely belongs to PROGMEM.

Take a look at an ASCII table such as the one here.
You could remove the first 32 ASCII characters which are the control characters and don't show up on the display. That would save 160 bytes. You will just need to make sure your index lines up.
You can then remove the last 127 characters which make up the extended character set. These are rarely used in the English language. This would save you an additional 635 bytes.
Overall that would save you 795 precious bytes.

I rem'd out line 153-281 and it seemed to solve the memory issue, the array wouldn't work without the first 32 charachters for some reason, started spitting gibberish - thanks a ton for the help will keep testing it until the panel is finished :)

There are many decoder devices that would do the job such as DLR1414, DLO1414, DLG1414, etc they even have the display integrated. Another solution is to add external memory such as a 2K by 8 eeprom or whatever. Program it such as it is a character decoder/generator. This will give you a lot more memory without using up the on chip memory.  I use to do this many years ago with 2716's. The address inputs would be the select and the output would be the decoded dot pattern.

@Gil why not turn that comment into an answer. :)

Ran into the same issue. Added the following line to setup():
// The following line is magic needed for pgm_read_byte() to function.
if (millis() > 100000L) Serial.println((uint16_t) font, HEX);

Note the Serial.println() is never executed, but the compiler doesn't know that.
Without this line pgm_read_byte() produces garbage.
With this line added to setup() the code runs fine.
Disassembling the code it looks as if without the Serial.println((uint16_t) font) the compiler optimizes away the begin address of the array, dropping "font" from the symbol table.
Complete sketch at https://github.com/koendv/retroleds


text:
Understanding how a tilt switch works
I am learning Arduino and pardon me if this is nooby. I am trying to make an LED glow when the tilt switch is tilted. The LED should not glow if the tilt is in normal position. The circuit and the code are in the attached image.
Based on my understanding of the code, I thought that when the tilt switch pin 5 is passed with HIGH signal from 5V the IF condition gets satisfied and tje LED on pin 13 would glow.
But it does not happen. The LED just glows before I tilt the tilt switch. Could you please clarify/correct my mistake. Thank you.

Attaching the code below as per suggestion
int ledPin = 13;
int switchPin = 5;

void setup() {
  pinMode(ledPin,OUTPUT);
  pinMode(switchPin,INPUT);
}

void loop() {
  Serial.begin(9600);
  if (digitalRead(switchPin) == HIGH) {
    digitalWrite(ledPin,HIGH);
    Serial.print("we are here");
  }
  if (digitalRead(switchPin) == LOW) {
    digitalWrite(ledPin,LOW);
    Serial.print("there");
  }
}

Don't paste an image of the code. Code is text -- just paste the text right into the question, select it and type CTRL-K to format it as code.

int ledPin = 13;
int switchPin = 5;
void setup()
{
pinMode(ledPin,OUTPUT);
pinMode(switchPin,INPUT);
}
void loop()
{
Serial.begin(9600);
if (digitalRead(switchPin) == HIGH)
{
digitalWrite(ledPin,HIGH);
Serial.print("we are here");
}
if  (digitalRead(switchPin) == LOW)
{
digitalWrite(ledPin,LOW);
Serial.print("there");
}
}

Edit your question -- don't put the code as a comment.

Check your tilt switch with the continuity setting on a multimeter to find out at what orientations it's considered "ON" and which are "OFF"

Did that Sir. Just figured it out :)

Thanks for the response, Even when I flick it ON/OFF the LED keeps glowing, I think I maybe making mistake on the pinmodes or something :S
If the orientation was the issue, then the other IF condition would have satisfied when I tilt the switch

The code is functional, besides the fact that you're probably filling up the serial port output buffer. Note that your loop() runs at probably close to half a million times  a second, and you are trying to write a string of text every time through the loop. Try commenting out the Serial.print() statements and see if that clears anything up.

How about using a pullup/pulldown resistor? When there is no connection from the input pin to any potential it will be floating

Thanks chrisl, Its what you said. The PULLUP.
Looks like I did not read the theory right. Switches are supposed to be connected to the ground, with PULLUP specified. I connected them to 5V.

Learning arduino with a tinkercad simulation? Do you have a real arduino board?

Yes I do have it. But I am a noobie and little paranoid that I might short it. So I learn using tinkercad and if it works then I try them out on Arduino

Is this a simple mercury switch?  You call it a tilt switch but I am not sure what you mean.

Understanding how PULLUP works lead to the solution. Also learnt that switches are supposed to be connected to ground. Thank you all for your time. Especially chrisl.

Switches aren't "supposed" to be connected to ground. It's just that if they are you can make use of the internal pullup instead of having to attach an external pulldown.

Don't post code as an image.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes


text:
How to program an SSD1322 display?
I'm new to programming. I would like to change the characters on an SSD1322 OLED display. Here are the photos.
Is this possible with an Arduino Uno? Is the program of the display in the display or in the Mega 2560?
Thanks for your help!

An SSD1322 is just a graphical OLED display, like the SSD1306 and many others. It just displays what it's sent. Whatever that thing is it's plugged in to is what is generating the graphics that are being displayed.

OK thanks for your answer,
so if I understand the program that manages the display is on the pcb or there is the 2560?

It's whatever the display is plugged into. It may be that 2560, but I don't know what that board is, so can't comment.

on the 2560 card there is an ISP connector
http://liedson.fr/1.jpg
is it possible to connect an arduino uno to read the program that is in the 2560?

no, it is most likely copy protected

yes that is possible, but I have a second blank pcb without a program,
I just wanted help with the procedure.
must it connect the pcb 2560 by the IPS with an arduino uno?
I can also pay the person who will take the time to help me work on it!

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
How to use a DC buck converter to regulate Uno R3 input voltage?
I have had a rough time trying to understand why this isn't working correctly. Quick background: I set up a system to pop open car doors using touch sensors. I heard that powering the Arduino Uno R3 straight off the car battery is not a good idea, so I bought a buck converter. I wired it up and calibrated the output on the converter for 5V. When I hooked it up to the Arduino (via the barrel jack), I experienced some odd effects. The output pins and the 5v power pins were only getting 3.5V.  I had to adjust the buck converter up to about over 7V in order to get 5v on the Uno.
Then the sensors started acting oddly. Auto triggering and alternately not working. Anyone know what I am doing wrong?
Converter I bought:  https://www.amazon.com/gp/product/B0159W0UL2/ref=oh_aui_detailpage_o07_s00?ie=UTF8&psc=1

Connect the output of the buck converter directly to the 5V (and GND) pin, thereby bypassing the voltage regulator. Or do as Michel said. I'd suggest the latter, if you are running from a car, as the battery voltage in a running car can have a lot of spikes.

The barrel jack needs 9-12 V, the internal voltage regulator of the Arduino will reduce this to 5 V.
Since you only supply 5 V, there is a loss in the internal voltage regulator why you probably get only 3.5 V.
And after applying 7 V, probably some (sub) system gets less than the necessary voltage, or there are occasional 'downspikes' lower than 5 V.
The default adapter that you use for supplying voltage to the Uno, also is 9V-12V. Also, check the polarity.
See the following link for more info:
What adapter

I did not know about the 9V.  I just assumed that since the board ran on 5v, it would need 5v in.  Makes sense now, but I still don't know what the converter should output to maintain the Uno's optimal 5V bus, while maintaining minimal drain on the car battery (efficiency).  Is there an efficient ideal voltage to output?

The Arduino can handle anything between 9 and 12V. Normally it is used if you have another device using 9 or 12V and you can use the same power source for both the other device and the Arduino. If you use 12V, there will be more heat generated in the Arduino, if you use 9V, there will be more heat generated in the buck converter.

If you are getting a clean 5v from the buck converter, you can/should run that directly to the 5v pin on the Arduino. Using the barrel jack(at 7-12V) still uses the on board linear(inefficient) Regulator to produce the 5v the board needs. You will want to ensure you are outputing a clean 5v during all phases of the car being on/off/startup.


text:
AnalogWrite not working in if statement
Arduino Uno with ATMega328P Processor.analogWrite is not working properly in if statement. It changes the brightness of the LED as if there wasn't any if statement at all.
There are 2 potentiometers to create an intervall in which to program increases of the LED brightness, starting at 40% of the maximum. When it's lower than the minimum value, the LED is turned off.
int ledPin = 6;
int sensorPot = 1; // it's a potentiometer for now
int maxPot = 7; // potentiometer
int minPot = 3; // potentiometer
int fortypercent = 255*0.4;
int brightness = 0;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(sensorPot, INPUT);
  pinMode(maxPot, INPUT);
  pinMode(minPot, INPUT);
  Serial.begin(9600);
}

void loop() {
  int start = analogRead(minPot);
  int maxVal = analogRead(maxPot);
  int sensor = analogRead(sensorPot);
  Serial.println(sensor/4);
  Serial.println(start/4);
  Serial.println(maxVal);
  if(sensor/4 > start/4) {
    analogWrite(ledPin,sensor/4);
  } else if(sensor = baslangic) {
    analogWrite(ledPin,LOW);
  } else if ((start < sensor < maxVal)) {
    brightness = sensor/4 - fortypercent;
    analogWrite(ledPin,brightness);
  } else if (sensor = maxVal) {
    analogWrite(ledPin , 255);
  }
}

Can't execute how? What happens?

Of course it can. What problem are you having? What output do you expect from this program? What output do you have instead?

Sorry, edited question

Please, be more specific, like “If I set the pot XXX to position XXX I expect the program to do XXX and instead ot does XXX”.

I updated my question

ORIGINAL RESPONSE, BASED ON DIFFERENT CODE
You are comparing sensorValue to see if it's ever less than minValue.
However, you have mapped sensorValue to range from 0 to 255, and minValue is set at 0. How can anything from 0-255 be less than zero?
NEW RESPONSE, BASED ON UPDATED CODE
One of your if statements: else if(sensor = baslangic) is not comparing, but assigning baslangic to sensor. To compare, use ==.
Your other if statement: else if ((start < sensor < maxval)) is wrong. C++ doesn't work this way. Maybe you want: if ((start<sensor) && (sensor<maxval))?
Instead, your statement evaluates like if ( (start<sensor) < (maxval) ), which means you are comparing the TRUE or FALSE of (start<sensor) to the int that is maxval.

I am analog reading minValue.

Indeed. So, what is connected to pin A3 (minPot) and what values from analogRead() is it providing? Use debug statements. I will retract this answer, since I misread the question.

Sorry for asking not well explained questions... Newbie here... Updated the question


text:
Arduino whack-a-mole game not working
Everyone, I am new to this. Currently I am trying to make a Whack-a-mole game for my school project. There will be a total of 6 moles (corresponding to 6 LEDs, which will light up randomly). At each moment, there will only be one LED lit up. The whole game duration is 30 seconds. At the end of the game, the score will be displayed.
I use a piezo electric sensor to detect the knock of the user. I program it in such a way that if the reading of the piezo sensor is greater than 50, it will take it as knock, and if the user knocks it correctly, one point will be awarded.
But unfortunately my code isn't working. The score displayed appears to be random numbers, doesn't work as it is supposed to be.
Here is my code, please hep me to have a look and provide me with some guidance. Thank you.
unsigned long time_since_reset;
int previousNum=0;
int currentNum =0;
int randomGenerator (void);
void light(int port);
int checker(int port);
int score =0;

void setup() {
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  time_since_reset = millis();
  while((millis()-time_since_reset)<30000) {
    randomSeed(analogRead(0));
    currentNum = randomGenerator();
    light(currentNum);
    checker(currentNum);
  }
  Serial.println("End Game");
  Serial.println(score);
}

int randomGenerator(void) {
  int cNum;
  cNum = random(3, 8);
  if(cNum!= previousNum) {
    return cNum;
  }
}

void light(int port) {
  digitalWrite(port,HIGH);
  delay(1000);
}

int checker(int port) {
  jump:
  int mole1 = analogRead(0);
  int mole2 = analogRead(1);
  int mole3 = analogRead(2);
  int mole4 = analogRead(3);
  int mole5 = analogRead(4);
  int mole6 = analogRead(5);
  while(mole1<10 && mole2<10 && mole3<10 && mole4<10 &&mole5<10 &&mole6<10) {
    goto jump;
  }
  if(mole1>50 && port == 3) {
    score++;
    digitalWrite(port, LOW);
  }
  if(mole2>50 && port == 4) {
    score++;
    digitalWrite(port, LOW);
  }
  if(mole3>50 && port == 5) {
    score++;
    digitalWrite(port, LOW);
  }
  if(mole4>50 && port == 6) {
    score++;
    digitalWrite(port, LOW);
  }
  if(mole5>50 && port == 7) {
    score++;
    digitalWrite(port, LOW);
  }
  if(mole6>50 && port == 8) {
    score++;
    digitalWrite(port, LOW);
  }
}

When including code in a stackexchange question or answer, first paste the code into the question or answer editing box; then in that editing box, highlight the code and press ctrl-k. Or highlight the code and click the {} icon in the toolbar at the top of the editing box. To highlight text click-drag across it or use the arrow keys while holding the shift key.  This will make code appear as code.

Could you add some sample serial output?

light() prevents checker() from reading anything for 1 second because of delay(1000);

if I don't include the delay(1000), the led will lights up and off very quickly, the players are unable to respond that fast. any suggestion to improve it?

The code as shown has a bunch of problems; the probably-most-important are as follows.
• score is not initialized.  Add score = 0; after
 time_since_reset = millis();
• As noted in a comment, the delay(1000) statement in light() prevents checking for whacks during the first second of a light being on.  This probably is undesirable – most people expect to whack a mole much sooner than a second after it appears.  If you want a delay there, make it at most 20 milliseconds. [See edit 2]
• The sequence randomSeed(analogRead(0)); currentNum = randomGenerator(); has a good chance of generating the same value of currentNum several times in a row, which may result in multiple counts for a given whack.
• Instead of saying randomSeed(analogRead(0)); within the inner loop, say it just after time_since_reset = millis(); or (probably better) in setup().  If analogRead(0) changes slowly, the same random seed may get used over and over, resulting in the same sequence of numbers from the random(3,8) expression.
• Your randomGenerator() routine has undefined behavior:  It doesn't return a valid result if the current random  number is the same as the previous one.  You could add a loop that calls random() again if the value is the same as before; but not returning a value results in  undefined behavior.
Edit 2:  When you turn a light on, record the current millis() time reading, say in onTime[i] for light i, and set flag isOn[i] true.  Later, when isOn[i] && (millis()-onTime[i] > targetDelay[i]), turn the light off and clear the flag (via isOn[i] = false).  Within checker(), a condition like port == 6 translates to isOn[6], an expression which is true when light 6 is on, else false.
The approach of using arrays like onTime[] and isOn[] and targetDelay[], variable subscripts, and recorded on-times has several benefits:  It lets you loop through lights, getting rid of that needlessly repetitious code in checker(); it enables other processing in the main game loop (such as whack-testing) to proceed independently of light control; it allows multiple moles to pop up at the same time; and it allows different moles to have different or varying up times.

in cryptography you want to re-seed only once per session. use a timer to get more than 255 seeds.

if I don't include the delay(1000), the led will lights up and off very quickly, before the players are able to respond to it, any suggestion on how to improve this? thanks

If you don't have a delay the LED will stay in the last state you set it to. Why would it turn off?

Others have already mentioned the issues with the timing, score initialization and random number generation.
On your checker function you have 2 errors and one ugly piece of code.
Ugly code first - goto is BAD. About the only time it's acceptable is under an error condition, the rest of the time if you find yourself needing to use a goto then look at how you can improve the code structure.
Errors - You exist after an analog input is > 10 but only count >50 as a hit. As they hit it the value will ramp up so they hit a target you could see a value of 10, exit your loop and not score anything. You need to use the same threshold for both. (Another style point, if you have the same magic number in two places (e.g. 10 or 50) consider making them constants or #defines rather than hard coded numbers. It makes it a lot easier to change them without forgetting one of the locations).
The second error is that you only turn the LED off if they hit the correct target, if they get the wrong one you light the next target but never turn the first LED off.
The code below should solve all of these issues.
int checker(int port){

  char exit = 0;
  int mole;
  while (!exit) {                // until we get a hit
    for (int i = 0; i<5; i++) {  // check each mole in turn
      mole = analogRead(i);      // read the sensor
      if (mole < 50) {           // if over the threshold
        exit = 1;                // exit the while loop after this check
        if (i + 3 == port)       // see if they got the correct target. i goes 0-5, port goes 3-8
          score++;
        digitalWrite(port,LOW);  // turn the LED off
        break;                   // break out of the for loop
      }                          // end if hit
    }                            // end for loop
  }                              // end while loop
}

after amending my code with your suggestions, it still don't work. after I removed the delay(1000) for the LED, it turns on and off very fast and the score showed at the end is a random number. please provide more guidance. Thanks


text:
Erratic behavior from 'randomly' generated values in array
Currently working on a data collection algorithm on the Arduino MEGA (ATMega1280) and I've run into a problem with some of the code I've written. I feel my problems may be stemming from the way in which I'm storing the sample points I've generated in arrays ats1 and ats2 or in the ways that I'm generating said sample points in generate_tspairs. Any insight would be appreciated.
I've defined a struct in an external file structs.h

struct tspair{
  int t;
  int s;
};

I have a function defined in generate_tspairs.h
    void generate_tspairs(tspair ats1[], tspair ats2[], int N, int reps1, int reps2, int reps3){

        int alpha = log(N)/log(2); //equivalent to log2(N)

        for(int j =  0 ; j < reps1 ; j++){
            double randomDecimal = (double) random(1000)/1000;
            int r = (int) pow(2,alpha-1)*randomDecimal + 1;
            int s = 2*r - 1; //s is a random odd integer on the interval [1,N-1]

                for(int n = 0 ; n < reps2 ; n++){
                    double randomDecimal = (double) random(1000)/1000;
                    int t =  (int) N*randomDecimal;
                    tspair temp = {t,s};
                    ats1[(j*reps2)+n] = temp;
                }

                for(int n = 0 ; n < reps3 ; n++){
                    double randomDecimal = (double) random(1000)/1000;
                    int r = (int) pow(2,alpha-1)*randomDecimal + 1;
                    int s = 2*r - 1; //s is a random odd integer on the interval [1,N-1]

                    randomDecimal = (double) random(1000)/1000;
                    int t =  (int) N*randomDecimal;
                    tspair temp = {0,s};
                    ats2[(j*reps3)+n] = temp;
                }
        }
    return;
    }

After initializing and setting my two arrays of tspair structs, I am printing the values of the first array ats1 using the following in driver.ino
  int reps1 = 3;
  int reps2 = 5;
  int reps3 = 5;

  tspair ats1[reps1*reps2];
  tspair ats2[reps1*reps3];

  generate_tspairs(ats1, ats2, N, reps1, reps2, reps3);

  for(int i = 0 ; i < reps1*reps2 ; i++){
    Serial.print("t: ");
    Serial.print(ats1[i].t);
    Serial.print(" s: ");
    Serial.println(ats1[i].s);
  }

However, oftentimes I will receive the exact same values across multiple runs of generate_tspairs or when printing the values it will not stop at the end of my ats1 but rather it will continue to print the same line ad infinitum. E.g.
t: 815 s: 523
t: 975 s: 523
t: 244 s: 523
t: 8689 s: -26051
t: 31001 s: 29184
t: -25856 s: 6939
t: -2057 s: 6939
t: -2057 s: 6939
t: -2057 s: 6939
t: -2057 s: 6939
t: -2057 s: 6939
t: -2057 s: 6939
t: -2057 s: 6939
t: -2057 s: 6939
t: -2057 s: 6939
t: -2057 s: 6939
t: -2057 s: 6939
t: -2057 s: 6939
...
...
...
t: -2057 s: 6939

What are the types and values of reps1 and reps2?

And why are you using  n <= reps2 instead of n < reps2? If it's intentional it should be noted in comment why.

Where/what are the definitions of the ats arrays, and specifically, are they large enough that you haven't written beyond the bounds of either? What are reps1 and reps2, and the significance of their product, reps1*reps2, which you've used as the limit of the printing loop counter?

@JRobert I neglected to include that information originally, my apologies. Edited the driver.ino section of the question to include that

@KIIV That was a typo on my part, it is < in the code I ran.

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
GCC msg "note: in definition of macro 'max'" error message
I'm using the ATtiny x5 series board, compiling my project (.cpp.ino file).  Whenever I use the max(a,b) macro, I receive this message:
"C:\Documents and Settings\<user>\Local Settings\Application Data\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.3-arduino2/bin/avr-g++" -c -g -Os  -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=attiny85 -DF_CPU=8000000L -DARDUINO=10609 -DARDUINO_AVR_ATTINYX5 -DARDUINO_ARCH_AVR   "-IC:\Documents and Settings\<user>\Local Settings\Application Data\Arduino15\packages\ATTinyCore\hardware\avr\1.1.1\cores\tiny" "-IC:\Documents and Settings\<user>\Local Settings\Application Data\Arduino15\packages\ATTinyCore\hardware\avr\1.1.1\variants\tinyX5" "-IC:\Documents and Settings\<user>\My Documents\Arduino\libraries\Pins_xxxxx" "-IC:\Documents and Settings\<user>\My Documents\Arduino\libraries\TinyWireS" "C:\WINDOWS\TEMP\build18f8c74edd63168be814edc24cb0a11a.tmp\sketch\AT85PWM.ino.cpp" -o "C:\WINDOWS\TEMP\build18f8c74edd63168be814edc24cb0a11a.tmp\sketch\AT85PWM.ino.cpp.o"
C:\Documents and Settings\<user>\Local Settings\Application Data\Arduino15\packages\ATTinyCore\hardware\avr\1.1.1\cores\tiny/Arduino.h:54:24: note: in definition of macro 'max'
 #define max(a,b) ((a)>(b)?(a):(b))
                        ^

What does note: in definition of macro 'max' mean, do I need to do anything about it, and if so what?
Searching google for the message gives lots of compiler output listings with the message, but the posting is always for another different message that is causing trouble.  None of the fixes from those posts address the max note: message.

Is that the only message? Can you please post your code, or at least a Minimal, Complete, and Verifiable example. I suspect it is something to do with the data types being used when you use max in some context.

I spent a good hour trying to package up something small for you before I decided to abort.

@Nick, I spent a good hour trying to package up something small for you before I decided to abort.  The basic problem seemed to be a function call where MAX was used to calculate one parameter, and a macro was used to try and extract a field from a structure for use as another parameter.  Because of C++'s insistence that structs are classes, and therefore a search for explicit conversion routine, the macro used to extract the field gets flagged along with all other macros in the function call.  This seems a tad overzealous, but it's better to have too much info...

And there's a 5 minute rule about editing comments.  Should be more like 30.  Some of us are slow thinkers, need to consult references, need time to edit....   Buzzzzzzzzzzz  your time is up, next contestant please!

I was recently working on another project where I got a similar message. However before it was the real error message/warning. The "note" line just tells you where the macro is defined. The "real" error/warning occurs when the macro is used (because that is where you might have signed/unsigned mismatches, for example).

I can reproduce your message easily enough:
#define max(a,b) ((a)>(b)?(a):(b))

void setup() {
 int b = 66;
 unsigned int c = 42;
 analogWrite (3, max (b, c));
}

void loop() { }

I get these warnings:
/tmp/arduino_modified_sketch_857720/sketch_aug31a.ino: In function 'void setup()':
/tmp/arduino_modified_sketch_857720/sketch_aug31a.ino:1:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define max(a,b) ((a)>(b)?(a):(b))
                         ^
/tmp/arduino_modified_sketch_857720/sketch_aug31a.ino:6:18: note: in expansion of macro 'max'
  analogWrite (3, max (b, c));

The point is that the warning note: in expansion of macro 'max' is just telling you where the macro is defined, so you can make sense of the real warning. The real warning is: warning: comparison between signed and unsigned integer expressions
So, reading them together, you are comparing (in the macro) a signed and unsigned number, and the compiler is warning you about that.

The message seems like a red herring, given that there is no problem with the max(a,b) macro definition. I suspect it is being flagged only because it was tangentially involved with a statement in error.

That's right. There is no problem in that macro per se. Macros can generate weird error message because they are just text replacements. For example:
max (the quick brown fox, jumps over the lazy dog);

That will generate a slew of errors, including a "note" to where max is defined. There is nothing wrong with max until you try feeding garbage into it.

Templates
That's one of the reasons I prefer to avoid macros if possible. You can do "max" with a template. For example:
#undef max   // throw away the original macro in the Arduino header file

template<typename T> T max (T a, T b)
  {
  if (a > b)
    return a;

  return b;
  }

Now you get slightly more reasonable error messages:
/tmp/arduino_modified_sketch_711186/sketch_aug31a.ino: In function 'void setup()':
sketch_aug31a:14: error: no matching function for call to 'max(int&, unsigned int&)'
   analogWrite (3, max (b, c));
                            ^
/tmp/arduino_modified_sketch_711186/sketch_aug31a.ino:14:28: note: candidate is:
/tmp/arduino_modified_sketch_711186/sketch_aug31a.ino:3:24: note: template<class T> T max(T, T)
 template<typename T> T max (T a, T b)
                        ^
/tmp/arduino_modified_sketch_711186/sketch_aug31a.ino:3:24: note:   template argument deduction/substitution failed:
/tmp/arduino_modified_sketch_711186/sketch_aug31a.ino:14:28: note:   deduced conflicting types for parameter 'T' ('int' and 'unsigned int')
   analogWrite (3, max (b, c));
                            ^
exit status 1
no matching function for call to 'max(int&, unsigned int&)'

Of course, now you've gone from a warning to an error, because the template wants a single type.
Notice the notes? That's just the compiler trying to be helpful.

You could make the template take two types if you are prepared to guess the return type (will it be the first type, or the second type?):
#undef max

template<typename T1, typename T2> T1 max (T1 a, T2 b)
  {
  if (a > b)
    return a;

  return b;
  }

Now you don't get an error or a warning, however the result will be the first type (T1) which may or may not suit you.

Twasn't the case.
You constructed an example were the max() macro operands were in error.  In my case, the max() macro operands were just fine, and the relevant diagnostics involved another macro.  max() wasn't part of the expression in error.

Regarding templates:  the max() macro comes with the Arduino IDE base.  Perhaps you would be in a better position than I to get the IDE to change over to templates.

you would be in a better position than I to get the IDE to change over to templates - If they were to do that, it would probably throw up heaps of warnings, or even errors, in code that currently compiles with only a warning. So they probably won't. max() wasn't part of the expression in error - yes, well I would like to see this reproduced before I could agree.

the relevant diagnostics involved another macro - it would help to post all the diagnostics, and not just the ones involving max. Plus the defines for this other macro, and the lines of code which produced the error.

Note to the future:
(My particular case was a function call with several parameters.  One had the max(a,b), and another parameter had an error.  It used a different macro, which may have pushed the compiler to flag every macro in the whole call).
The message seems like a red herring, given that there is no problem with the max(a,b) macro definition.  I suspect it is being flagged only because it was tangentially involved with a statement in error.
Since it wasn't part of the problem, the compiler couldn't say anything specific about it or the code it generated.  Therefore the flagging message then ends up saying "in definition of macro" (kind of a default of last resort) since it couldn't say anything more specific.
If you ever get one of these, particularly from a system provided macro, ignore it until you've diagnosed your other problems.
Ignore the fact that the error message is first in the listing, and the statement using the macro doesn't get flagged until after several other statements are flagged.
Again, I suspect that compiler feels obligated to say something about the macro because it was used.  But since it's not part of the problem in the statement where it appears, it doesn't get flagged there.  Instead the compiler puts the message at the top because it has to go somewhere, but the compiler can't/doesn't want to associate it with the statement where it was used.
The solution worked for me, but a language lawyer or compiler developer may say my explanation has no basis.


text:
WizNet W5100 not connecting to modern switches and routers
I have an Arduino data collector with a W5100 module (see bottom of picture). Simple fixed IP connection:
 byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
 byte ip[] = { 192, 168, 1, 242 };
 Ethernet.begin(mac,ip);

This works with my old routers (Asus WL500, TP-Link MR3420), but fails to connect when plugged in a gigabit switch or my new router (D-Link DWR-116). The connection LED on the new devices does not lit up or blinks slowly, showing repeated connection attempts. So the W5100 fails to make the physical connection.
I made it work by adding my 10-year old Surecom switch to the mix, but wonder what the problem could be. Is there some cable configuration that is used by the W5100 but have been removed from these new network devices? (Not sure if the cable is cross or straight, trying another cable is messy, the whole thing is built in the wall.)

Check the IP address. Might not be the correct sub-net.

I did that already. Both routers are set to 192.168.1.1. Also, replacing the router is not the only way to make it go wrong, it was enough to plug it to the switch instead of the (old) router.

Check the Ethernet module power supply.

This thing has been running continuously for 4 years now. It just stops working when I try to plug it in to a modern router or switch.

I think your problem is due to the MAC address that is being loading into the W5100.  Try setting the 2 low order bits of the first byte to 0.
These bits define whether the MAC address is unicast or multicast and whether it is private or universal.  Some switches appear to block ARP requests if these bits are set incorrectly.
I changed the first byte of the MAC address from x'47' to x'44' and things started working.

Thanks, great tip! Experimented a little, with strange results: my router accepts x46 but not x44, and my switch accepts x44 and refuses x46. Left it at x46, it doesn't need a Gigabit switch to send a few bytes.

I just made a setup on my Dell PowerConnect and it starts to accept the W5100.
I had to change the port speed to 10M and it starts working. The 100M and 1000M was not accepting the w5100.
Before, I had a CISCO wifi 10/100M wired connection between it and w5100 and it connects fine, but this isn't the main network on my company.

sounds like a mac address issue.
I googled for Tp-Link MAC address bytes and it worked perfectly. (it is first 4 bytes)

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Uploading a sketch causing an error message in Arduino Uno
avrdude:

no programmer has been specified on the command line or the config
  file
           Specify a programmer using the -c option and try again

On the "Tools" menu choose "Programmer:" and specify AVRISP mkII; be sure that you've also chosen the appropriate "Board:" entry for the Uno.

yeah i  know all that but it keeps showing me the same error!!!

Describe your environment:  Windows? Unix, which one? Which version of the Arduino IDE?  Or, are you using Eclipse or another IDE?  Perhaps you need to re-install?  Has it ever worked?  Does, "Get Board Info" work?

Oh, are you trying to use the command line tool (avrdude?)

I fixed it. I just reinstalled the drivers.


text:
Problem with nodemcu esp-01 can't connect to wifi
i've been working on a project that im using an esp8266 nodemcu-01 as described in the title, and i've been having some headache with this module, first because after searching i figured out that the commands LOW and HIGH are inversed as in LOW outputs 3.3v e HIGH outputs low tension, so i began to grow worried about the possibility that other programming resources may follow the same situation. But with that problem a part, i've been trying a few different codes including the one found in the sketchbook examples and still couldn't connect.
Also another weird problem, is that i was working working with the baudrate set on the arduino IDE settings on 115200, and so is the Serial.begin, that is also set to 115200, however i can only read properly the continuous dot that is contained in the while loop "........." when i set it to 74880, which another thing that i was trying to understand. I also forgot to mention that it keeps spamming dots but does not connect at all.
And to conclude, my problem resumes in not being able to connect to any wifi i've tried, i tried my friend's home and also 4g, both did not work, here's the code, which we tried first:
#include <ESP8266WiFi.h>

char* ssid = "Net Wi-fi";
char* password = "testingtest";
//
void setup() {
  WiFi.begin(ssid, password);
  Serial.begin(115200);
  while(WiFi.status()!=WL_CONNECTED)
  {
    Serial.print("Conecting");
    delay(500);
  }
  Serial.println("");
  Serial.print("IP:");
  Serial.print(WiFi.localIP());
}

void loop(){

This was the original try, using the arduino sketch example:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

const char* ssid = "Net6271";
const char* password = "megaman";

ESP8266WebServer server(80);

const int led = 13;

void handleRoot() {
  digitalWrite(led, 1);
  server.send(200, "text/plain", "hello from esp8266!");
  digitalWrite(led, 0);
}

void handleNotFound(){
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET)?"GET":"POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i=0; i<server.args(); i++){
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
}

void setup(void){
  pinMode(led, OUTPUT);
  digitalWrite(led, 0);
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS responder started");
  }

  server.on("/", handleRoot);

  server.on("/inline", [](){
    server.send(200, "text/plain", "this works as well");
  });

  server.onNotFound(handleNotFound);

  server.begin();
  Serial.println("HTTP server started");
}

void loop(void){
  server.handleClient();
}

Board setting: Generic ESP8266 Module.
Crystal Frequency: 40MHz.
Flash Frequency: 80Mhz.
Upload Speed: 115200.
Flash Mode: DIO.
Flash Size: 512k no SPIFFS.
pls help.

ESP-01 modules use 26 MHz crystal. Set the Crystal frequency in IDE to 26 MHz.
Both io pins (0 and 2) on esp-01 have pull-up circuit. That is why you think you measured 'inverted' logic.

Thank you for replying my good sir, when you suggest setting the crystal frequency to 26Mhz i assume that's the fix for the baud differences in serial monitor? Also, on the second post i assume its referred to the inversion of logic? thanks but what do i do about wifi not connecting? it keeps sending "." and does not connect.

erase the flash with esptool and the try again the sketch

Thank you sir, you are a true legend, thanks for helping me out, your suggestion worked perfectly :)


text:
AnalogRead(0) always returns 0 on RFduino
I'm using RFduino to do analogRead at pin 2 and pin 0. Pin 2 works perfectly, and I got the result. However, for pin 0 it returns all zero.
#include <RFduinoBLE.h>

static const int topPin = 2;
static const int bottomPin = 1;

int top;
int bottom;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(topPin, INPUT);
  pinMode(bottomPin, INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
    RFduino_ULPDelay( SECONDS(0.01) );

    bottom = analogRead(bottomPin);
    top = analogRead(topPin);

    Serial.print(top);
    Serial.print(" ");
    Serial.print(bottom);
    Serial.print("\n");
}

I double checked the wires and it's OK. I measured the voltage across pin 0 and it's 3.3V. How do I fix this problem? There's no shortage between pin 0 and 3.3V.

I don't see any pin 0 read.. Also IIRC the analog pins on Arduino are aliased by A0, A1... rather than the number.

It's RFduino, a variation of Arduino. And yes, there's a typo in the code

Soo.. shouldn't it be A0, A2 rather than 0 and 2?

No. Pin 2 works perfectly. If it's A0, A2 it would be a compilation problem.

You don't have to set them as inputs with pinMode. It's my understanding that pinMode is for digital pins only. Comment out those pinMode lines and see if it works.

Analog pin numbers do not start at 0. Arduino pin 0 is a digital pin. Analog pin A0 is an alias for the first analog pin. A0 is a predefined constant.

Yes they do. You can use analogRead (0) to read from pin A0. You also don't need to do a pinMode for it. The notation A0 is for when you want to use an analog pin for digitalRead or digitalWrite (which you are allowed to do).

@DzungNguyen if there is a typo in the code than please fix it by editing your question so to make it clear what you are doing. Also a wiring diagram would help along with the description of any shield/module attached (if any).
Also note RFduino is not ATmega328 based, but ARM Cortex M0...

Without RFDuino specs handy, I'm guessing - but I think it's likely - that the A/D converter gets shut down in an ultra low power sleep and requires some amount of time to wake up. The mis-reading pin, pin 0, is the one your sketch reads immediately on waking. That read call probably takes long enough that the A/D wakes up by the time your read pin 2 so it gives a better reading.
Try switching the order in which you read the pins and see if pin 2 mis-reads if you try to read it immediately after waking. If it does, the cure may be as simple as a 10-100 uSec delay between waking and trying to read any analog data. I just pulled that number out of the air; you might start with a couple of milliseconds and see how low you can make it before you start to see errors, then double that amount.

Thanks for your confidence, but unless this actually worked, I think @edgar nailed this one.

I couldn't find an usable datasheet for the RFduino, seems like a very
poorly documented board. But I found an enlightening comment in the
source code of the RFduino library:

Only pins 1-6 is avaliable [sic] for using as ADC inputs

If you read the source, it is clear that calling analogRead() on an
inappropriate pin is supposed to return 0.


text:
What is the worst time case for Arduino Mega?
I'm going to implement home automation using an Arduino Mega with 8*6=48 channels relay in my new home. I have prepared an Android app for an HC-05 Bluetooth controller. How much time can I keep running an Arduino Mega with all the appliances in a home? Can I keep it working 24/7 for a while?

That shouldn't be a problem. Just make sure you get a proper power supply. I'd also suggest using the watchdog timer, so that if the program somehow hangs, it will reset itself. Maybe tie the reset pin of the HC05 to an Arduino pin, so you can reset it. That way you never have to manually reset the system if anything happens. Also, maybe have a certified electrician take a look.

Can I keep it working 24/7 for a while?

yes, if properly designed.

Your answer is rather terse. Please expand on it.

Yes.
(For better guidance than that, we'd need to know more.)

I would be wary of going "all in" if the MCU holds+controls the state of all the relays, especially if there's networking happening in the sketch. That creates a single-point of failure for the whole house. I've found that a brief power outage or an MCU freeze/reboot resets the state. That can be frustrating and downright dangerous in a emergency situation.
An obvious solution is to save the relay states in EEPROM or externally on a server. The issue with those is that EEPROM wears out, and your server might not be available soon after a power-cycle when the MCU needs it to resume (router re-connecting, computer rebooting slower than MCU, etc).
The real solution, and the one that preserves life-safety is having local hardware state for each relay. You need the ability to both read state from the Arduino, and change the state from the Arduino. This can be as simple (yet expensive) as physically latching relays, or a capacitor-backed 1-bit state machine like an RS flip-flop. You can build the flip-flop in a variety of circuits, from shift registers, to a 555, to a simple NPN+n-channel MOSFET coupling (my pref).
The big downside is that this needs two pins for each relay. But, with such "smart relays", you can unplug the Arduino and nothing happens around the house. It also allows non-Arduino things (even a simple button/switch) to control the state of a relay, no matter what's happening with the Arduino at the time, but with the ability of the Arduino to react to that change and not over-write or forget the state. The MCU can reboot on a schedule to keep responsive, without anyone noticing the reboot.
Yes, it adds more complexity and cost, but a manageable amount of both, and the satisfaction difference is hard to truly express. In short, any system should work as reliably as lights did 100 years ago: switches work, and never unexpectedly change. If lights are not working or are turning off unexpectedly in a small fire, things can get ugly quick, especially with guests.


text:
Nick Gammon "Camera shutter speed timer"
I am reading the period of pulses from a 600ppturn shaft encoder, using the FreqPeriod library, by Martin Nawrath.
This works using counter1 and the comparator on pin6 and pin7 on the Arduino Uno.

The period duration for 1-2500Hz is being used in a midi musical instrument to give a speed to volume and a note change at a fixed speed.
This has worked well on the Uno but now I want to use a Mega (which does not have both comparator pins).
So I have tried using the Nick Gammon interrupt sketch. This has produced very erratic results returning both positive and many negative numbers (shown by using "volatile long period;" in the monitor.
Can you tell me what is happening and would it be better to use a counter instead of interrupts?
Hope I have given enough information to be getting on with, many thanks.
// Camera shutter speed timer
// Author: Nick Gammon
// Date: 15th January 2012

volatile boolean started;
volatile unsigned long startTime;
volatile unsigned long endTime;
volatile unsigned long period;
volatile unsigned long lfrq;

// interrupt service routine
void isr () {
    if (started)
        endTime = micros ();
    else
        startTime = micros ();
    started = !started;
} // end of Pulse Width

void setup () {
    digitalWrite (2, HIGH); // pull-up
    Serial.begin (9600);
    Serial.println (" Pulse Width test = ");
    attachInterrupt (digitalPinToInterrupt (2), isr, CHANGE); //CHANGE RISING
} // end of setup

void loop () {
    if (endTime) {
        period = (endTime - startTime) * 32 ; // pulse width?
        Serial.print (" \n  ");
        Serial.print ( " period =  ") ;
        Serial.print (period) ;
        lfrq = 16000000.0 / period;
        Serial.print(" Hz = "); // one rev per sec = 26666 micros period
        Serial.print( lfrq );
        endTime = 0;
    }
} // end of loop

If you simply want frequency and period, in the Interrupt Service Routine, simply count the times the ISR is called.
In the loop() at regular intervals, say 10 mS, look at the count and multiply up to get the counts per second. If you use 10mS intervals,
multiply by 100. That is your frequency in Hz. The inverse, i.e. divide 1 by your frequency in Hz, and that is your period. Then reset the count back to 0.

Why are you using the analog comparator for what is a digital input? An encoder provides pulses, not a range of analog values. I have a page about rotary encoders if that helps.

I am  reading the period of pulses from a 600ppturn shaft encoder, using FreqPeriod Library , by Martin Nawrath because I was very new and ignorant ( but now slowly learning)  to programing. Martins   sketch answered my need to produce a continuous   series of pulse period measurements at low Hz to compute a rising volume with turning speed and to trigger a midi note change a speed set by a pot`. This sketch is the only one I found that worked out of the box .

his sketch is the only one I found that worked out of the box and was happy with . It is only now  I am boning up on interrupts and timers with my need to use the  Mega . . PS this is my instrument on YouTube ;  https://www.youtube.comwatch?v=Hquj4RQdFmI

Hold The Pages! I have got the above Nick Gammon sketch working to producing a chain of readings.

I think the problem started when I updated my IDE from 1.6.0 to 1.8.0. I have had problems compiling . The only way I found to make some sketches compile and upload was to include a library such as  <SD.h> . I since realized that "digitalWrite" may not be supported , replacing with  "pinMode" and removing <SD.h> ,the sketch now works as I am sure intended. I will now incorporate this into my existing musical instrument sketch and let you know how I get on.

Could this be so?

because the code is faulty: there is no assurance of atomicity between startTime and endTime. ie. the interrupts could have arrived, multiple times, while the if loop is executing.
two ways to fix it:

calculate period in the isr; or
clear endTime once the clock starts in the isr.

Can you tell me what is happening [...]?

Not really, but here is a wild guess: your input signal is bouncy, the
ISR fires too often, your loop cannot keep up with the rate, and you end
up accessing endTime in the ISR and loop simultaneously.
If you have a scope, look at your encoder signal. Is it clean?

would it be better to use a counter instead of interrupts?

Using the input capture feature of a timer will give you the best
possible accuracy, as you will have single-cycle resolution. In
contrast, micros() has only 4 µs resolution (64 times worse) and
the ISR may be delayed by up to ≈ 16 µs by the TIMER0_OVF
ISR.
You can use the FreqPeriod library you linked to as an inspiration for
writing your own timer-based code, but it will require some changes:

As pointed out by Nick Gammon in a comment, you don't need the analog
comparator, nor the conditioning RC network, as the encoder's outputs
are already digital. Or you may use a low-pass filter if the encoder
is bouncy.
You will use the input capture pins of either timer 4 (digital pin 49)
or timer 5 (digital pin 48). The other input capture pins are not
available on the Mega's pin headers.
You will replace ISR(ANALOG_COMP_vect) by either ISR(TIMER4_CAPT)
or ISR(TIMER5_CAPT) (the relevant “capture event” ISR). No need to
adjust a comparator threshold in the ISR.
In the begin() method, you will leave the analog comparator alone,
and you will enable the capture event interrupt.

Obviously you will have to study the
datasheet
before start coding.

Hold The Pages! I have got the above Nick Gammon sketch working to producing a chain of readings.  Please excuse my lack of comprehension, using this sketch will I get a reading for all pulses? Although I do not seem to get two readings using pulse edge"CHANGE" as apposed to  one reading with pulse edge  "RISING" why is this, am I wrong in my thinking ?  Two readings per pulse period I think should be better than one?  I  still can not comprehend  what would be better for my needs counter or interrupts. Does the Martin Nawrath sketch use interupts or counter ,or both ?

While you are doing all those things with those volatile variables in the loop function, the interrupt can still be firing.  If it fires in the middle of a read of startTime or endTime then you get might get part of the variable holding old value and part holding new value and when you put it together it makes garbage.
You need to do a cli() at the beginning of loop to turn off interrupts and quickly make local copies of all those variables and then sei() to turn interrupts back on.  Now you can safely work with the copies you made.


text:
Use ATtiny85 to perform initial config on a Cisco router using its USB console port
We have 200+ brand new Cisco routers that have USB console ports (but not the old RJ45 serial console ports). This is quite frustrating because the routers didn't ship with console cables and Cisco wants to charge $60 for their proprietary USB->RJ45 serial adapters.
When I plug the router in to a computer using a standard USB cable (mini USBb on one end and USB on the other end), it shows up as a virtual com port and allows me to configure the router if I have a VCP driver installed. More specifically it shows up as a "CP2105 Dual USB to UART Bridge Controller". Here's the full lsusb -v output for the router:
Bus 001 Device 005: ID 10c4:ea70 Cygnal Integrated Products, Inc. CP210x UART Bridge
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x10c4 Cygnal Integrated Products, Inc.
  idProduct          0xea70 CP210x UART Bridge
  bcdDevice            1.01
  iManufacturer           1 Silicon Labs
  iProduct                2 CP2105 Dual USB to UART Bridge Controller
  iSerial                 5 12345678
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           55
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              3 Enhanced Com Port
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              4 Standard Com Port
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               0
Device Status:     0x0000
  (Bus Powered)

Is it possible to have an ATtiny85 board (eg Digispark) interface with the router via its USB console port to send several commands over the link to perform a perform basic initial config?

That's not how USB works.

why not write a computer program?

@IgnacioVazquez-Abrams how is this not how the "Universal Serial Bus" works? The router presents as a USB UART interface. All the Attiny needs to do is understand the protocol. There's plenty of projects where the Attiny itself pretends to be a USB UART HOST but I can't find any where it acts as a client. If it can act as a host, surely it can act as a client.

"If it can act as a [device], surely it can act as a [host]." You grossly overestimate USB's flexibility. The relation between host and device is not symmetrical, on purpose. It makes USB devices cheaper and easier to implement at the expense of making hosts more complex.

@Juraj because then our techs will have to lug around a computer to every router ensuring it is kept charged over several months visiting 200 locations. It would be vastly easier if they could plug in an attiny which costs $50 to make 10 and which can draw its power from the USB port, it then acts as a UART client and issues some choice commands to configure the router, it turns on a green led and the tech unplugs it. Job done at a fraction of the time and cost.

@IgnacioVazquez-Abrams it's a single protocol. If it can decode uart-over-usb then it can encode uart-over-usb

I have no problem with you writing a software USB host implementation for the ATtiny85 and proving me wrong.

Aaand back to square 1

you think all strings needed for router configuration fit into Attiny memory with software the (impossible) usb host implementation?

You'd have to implement USB host. Which I haven't seen done before (but I might have missed it). First, I'd ditch the ATTiny85 idea. It's less powerful than the other Arduino's, and a lot harder to work with/debug. I'd suggest looking into the USB-host shield. The Arduino Due has USB-OTG, so that might maybe be an option. A maybe even better option could be to have an Android phone with a USB-OTG cable and some Serial Console App.

It's been a couple of decades since I was programming Cisco routers, firewalls and switches but I appreciate you pain. Like @Gerben says, you need a bigger processor, an ATtiny85 isn't going to be able to hold a lot of config and even the basic configs I used were about 4 to 6KB.
If there is anything in the configs that is different, you idea is going to hit problems.  Are the device names and passwords all the same? In which case you probably want the engineer to be able to set some configuration data in you "programmer", could they set this specialisation data using their mobile phone?
I doubt you will have any problem connecting an "Arduino" via serial (RS232) to a Cisco router. However you now have to encapsulate the serial in "USB", which I don't think will be straight forward for an "Arduino".
I can't think of an option that doesn't require power, but as an alternative to your idea what about using a Raspberry Pi to connect to the router via USB. Stick a touch screen on it and a battery pack to power it.

Can I use a ATtiny85 board (eg Digispark) as a USB CDC device?
Yes!
If I have got this right, to be able to communicate with a USB serial device you need to have USB CDC support and if you want it to fake a keyboard/mouse you need HID.
The Digispark have a CDC library https://digistump.com/wiki/digispark/tutorials/digicdc
But it has its limitations, take a lot of RAM ( ~2K) so to use a Arduino Leonard/Arduino Micro make more sens and then you could add a SD card as well so you can have your commands easily modified on a SD card.
I have the same idea, but I fetch the config from a TFTP source so my commands needed on the Digispark/Leonardo/Micro is minimal.


text:
Why does Serial.print print only a value for 0-84 for a 100 integer array?
int a[100],i;
void setup() {
  Serial.begin(9600);
}

void loop() {
  for(i=0; i<100; i++) {
    a[i] = i;
    Serial.println(a[i]);
  }
  exit(0);
}

It's because you're using exit(0).  That turns off interrupts and goes into an infinite loop. However, serial printing is first placed into a buffer, and each character is then removed from that buffer in turn and sent out through the serial port.
That's all fine, up until the end when you use exit(0);, and what is left in the serial buffer to send never gets sent because interrupts are disabled.
There is never really any cause to use exit() on a microcontroller - after all, where can it "exit" to? There's no OS to exit to. So it does the next best thing which is as close to doing nothing as reasonably possible.
Instead, if you want to "stop" your program you should use a simple while(1); which will allow interrupts to still trigger.
Alternatively, if you really want to use exit(), you should flush the serial first:
Serial.flush();

That function will block until the transmit buffer has been fully emptied by the interrupt and the last byte has left the UART's TX shift register.

And from this answer (assuming more than 1000 bytes of RAM) the UART's buffer will be 64 bytes, which is just enough to hold the remaining 15 numbers (two bytes + CR + LF each) with four bytes left over.

I wouldn't say that one shouldn't call exit() on a microcontroller. Rather, one shouldn't call a simple infinite loop exit(), suggesting it's a proper POSIX function.


text:
Stop Led's from blinking
My code:
// Pin 13 has a LED connected on most Arduino boards.
// give it a name:
int led = 13;
const int buttonPin = 2;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
}

// the loop routine runs over and over again forever:
void loop()
{
  bool buttonState = digitalRead(buttonPin);
  while (buttonState == LOW)
  {
   digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
   delay(1000);               // wait for a second
   digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
   delay(1000);               // wait for a second
   }
 if (buttonState == HIGH){
   digitalWrite(led, LOW);}
  }

The last line of code:
if (buttonState == HIGH){
   digitalWrite(led, LOW);}

Is what I tried using to turn the led off from its continuous blinking state. So the point of this project is to make the led's blink with a button, then turn them off with the same button. This has been bugging me for hours and I've done all the work but can't seem to get this last part done. What is being done wrong here?
EDITED for clarification:
The intention is that with each push of the button the LED is toggled between a blinking and a no-blinking state. The state of the LED is not driven by the level (pushed/unpushed) of the button itself, but by the pushing action itself.

What do you want to happen? Press once to start blinking and again to stop blinking? Blink while the button is pressed? Something else?

Yes the first thing you said.  Press once to start blinking and again to stop blinking

can i know how to have a button to trigger blinking of led and another button is to stop the blinking ?

It makes sense to make switch-testing fairly independent of blink-control.  That's done in the following code, which turns blinking on or off each time a button is pressed.  With this code, between button presses the LED either is off or it blinks at about a 2 Hz rate.
enum { LED=13, ButtonPin=2, BounceMS=50, BlinkMS=256 };
unsigned long buttonAt;
bool blinky, bouncy, buttonState;

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(ButtonPin, INPUT_PULLUP);
  blinky = bouncy = buttonState = false;
  buttonAt = millis();
}

void loop() {
  // Detect button changes
  if (bouncy) {
    if (millis() - buttonAt > BounceMS)
      bouncy = false;       // End of debounce period
  } else {
    if (digitalRead(ButtonPin) != buttonState) {
      buttonState = digitalRead(ButtonPin);
      buttonAt = millis();
      bouncy = true;        // Start debounce period
      if (buttonState) {    // Was button just pressed?
        blinky = !blinky;   // Toggle blink-state
      }
    }
  }
  // Control light-blinking
  if (blinky) {
    // Turn LED on for BlinkMS ms, then off for same
    digitalWrite(LED, (millis() - buttonAt)%(2*BlinkMS) < BlinkMS);
  } else {
    digitalWrite(LED, LOW);
  }
}

EDITED
The Arduino loop() function makes the use of a while loop redundant in this case. Even worse: the way you've implemented that while loop prevents buttonState from being updated, thus getting stuck in the loop.
What you actually need is to use timers to blink the LED, and a 2-state machine driven by HIGH to LOW button transitions.
Try this instead:
#include "Timer.h"

// Pin 13 has a LED connected on most Arduino boards.
// give it a name:
const int led = 13;
const int buttonPin = 2;

// declare state variables as global
bool buttonState = LOW;
bool buttonState_prev = LOW;
bool toggleBlinking;
bool blinkState;

// declare a Timer object so blinking can be done without loosing button presses
Timer timer_b;
int blink_id;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  // initial state: toggle led each 1000 ms
  blink_id = timer_b.oscillate(led, 1000, HIGH);
  blinkState = true;
  toggleBlinking = false;
}

// the loop routine runs over and over again forever:
void loop() {
  // Update the timer (required)
  timer_b.update();

  // check if button has been pressed (HIGH to LOW),
  // then debounce it and raise toggle flag
  buttonState = digitalRead(buttonPin);
  if ((buttonState != buttonState_prev) && (buttonState_prev == HIGH)) {
    // simple button debounce (confirm press after some ms)
    delay (50);
    buttonState = digitalRead(buttonPin);
    if (buttonState != buttonState_prev) toggleBlinking = true;
  }

  // keep current LED state unless the button has been pushed
  switch (blinkState) {
    case true:
      // if button has been pushed, stop blinking and change LED state
      if (toggleBlinking == true) {
        timer_b.stop (blink_id);
        blinkState = false;
      }
      break;
    case false:
      digitalWrite(led, LOW);
      // if button has been pushed, start blinking and change LED state
      if (toggleBlinking == true) {
        blink_id = timer_b.oscillate(led, 1000, HIGH);
        blinkState = true;
      }
      break;
  }

  buttonState_prev = buttonState;
  toggleBlinking = false;
}

NOTE: You'll need to install the Timer.h library. I'VE TESTED MY CODE AND IT WORKS.

That's not a deadlock, but otherwise good :-)

You're right, thanks. I'll edit the answer.

Your code just makes the Led's blink once... I understand what you are trying to do here but I wanted so that the led's blink continuously once the button is pressed. But, when the button is pressed again, they stop blinking. Like I said, This makes the led's only blink once then stop blinking without having the button pressed...

OK, I'll see your using a pull-up. I'll check it.

Yes sorry, I should've given more details :/

@EnricBlanco any updates? sorry I've just been on this for quiet a while and need some explanation about the problems..

I've edited the answer, take a look.

As the OP explained in a comment, what he is trying to achieve is to have a button alternate between blink and off, not having the button to be pressed to shut down the led.
This can be done in this way:
bool prevButtonState;
bool ledBlinking;

void loop()
{
    bool buttonState = digitalRead(buttonPin);

    if (prevButtonState && !buttonState)
    { // Pressing edge: there is a transition between high and low
        ledBlinking = !ledBlinking;
    }
    prevButtonState = buttonState;

    if (ledBlinking)
    {
        digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
        delay(1000);               // wait for a second
        digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
        delay(1000);               // wait for a second
    }
    else
    {
        digitalWrite(led, LOW);
    }
}

This, however, leads to a very long time between successive checks of the button (since there is a 2s delay between cycles). You can solve this using the millis function:
bool prevButtonState;
bool ledBlinking;
unsigned long prevMillis;

void loop()
{
    bool buttonState = digitalRead(buttonPin);

    if (prevButtonState && !buttonState)
    { // Pressing edge: there is a transition between high and low
        ledBlinking = !ledBlinking;

        prevMillis = millis() - 1000; // Force a check
    }
    prevButtonState = buttonState;

    if (ledBlinking)
    {
        if ((millis() - prevMillis) >= 1000)
        {
            prevMillis += 1000;
            digitalWrite(led, !digitalRead(led));
        }
    }
    else
    {
        digitalWrite(led, LOW);
    }
}

Next there is the debounce problem, but this becomes OT. Suggestion: use the Bounce2 library to manage the button if you experience bounces

No, I do want to use the button to swith the led off.. Like a switch and a light bulb.. the only difference is that the lighbulb blinks.

In this comment you say that you want one push -> led blink, another push -> led off. This is what my code does. Your code is keep pressed -> led blink, leave unpressed -> led off

while (buttonState == LOW)

gets you trapped in an endless loop, once buttonState == LOW.
You have to poll buttonState inside this loop if you ever want to get out of it.
However this is not enough for your purpose. What you really need is a (boolean) variable - let's name it blinking, for instance - which changes its value each time you see a falling edge on buttonState.
Then check this variable's value in an if/else clause like this:
if (blinking == true)
{
   digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
   delay(1000);               // wait for a second
   digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
   delay(1000);               // wait for a second
}
else
{
   digitalWrite(led, LOW);}
}

But with this you will soon face the next problem: The polling speed for your button is very low, because of the very long delays, which keep you about 2 seconds inside the if clause.
Try setting up the blink cycle using a PWM, as described here
Then use the if clause above to set the PWM duty to 50%, and the else clause to set it to 0%.

So you want me to put If (buttonState == HIGH) inside the while loop?

@Utsav That won't help. The buttonState doesn't reflects current state of pin. The digitalRead does.

@KIIV so I put another bool buttonState = digitalRead(buttonPin); inside the while loop and then I also cut and pasted the If statement inside the while loop. They still do not produce the outcome :/ i'm sorry I couldn't really implement what you wanted...

@Utsav no, you want to update buttonState, not to create new one and shadow the other one from the outside of scope.

When I create this new bool variable called 'blinking', do I set the variable with a number? like: bool blinking = 0; or do something else? I am quite confused..

This answer is somewhat misleading. Polling buttonState inside a while(buttonState==LOW) loop doesn't achieve anything.

try this:
if (key_pressed()) digitalWrite(LED_PIN, (digitalRead(LED_PIN)==ON)?OFF:ON);
else digitalWrite(LED_PIN, OFF);

define ON/OFF based on your led connection.
Edit.
If you want the button too change the mode of led blinking, try this.
    if (btn_pressed())                  //if btn falling edge detected
        btn_status ^= 1;                //flip the last bit. btn_status += 1; works as well
    if (btn_status & 0x01) led1_flp();  //flip led1
    else led1_off();                    //otherwise, turn off led1

    //flip led2
    IO_FLP(LED_PORT, LED2);

the logic is fairly simple: if the button is pressed (active low), toggle btn_status. if btn_status is 1, blink the led1.
basically, press the button, led starts to blink; press the button the 2nd time, led stops to blink;
led2 is always blinking, to show concurrency of the code.
here it goes in action.

the code is written for a pic but basically runs on any mcu.


text:
How does the build process in Arduino IDE work for ESP8266
How does the build process for esp8266 work in arduino IDE. Arduino ide uses avr-gcc to compile programs For atmel micro controllers. Does it uses same for compiling programs for esp8266?

Does it uses same for compiling programs for esp8266 ?.

No. It uses xtensa-lx106-elf-gcc. The compiler has to match the architecture.
Most of the build "process" (as in the actions that are taken) is the same, but executables specific to the EXP8266's XTensa core are used. There's also a few extra things in there, like building the (optional) SPIFFS image, etc.

What about uploading code to the board, does it use avrdude for that. Is uploading process same for various boards like nodeMCU or wemos D1.

No, it uses the ESP8266 specific program, called esptool.  Every executable run is the ESP8266 specific one.


text:
What's wrong with my IR sensor
I bought some 'lucky dip' IR sensors from China, no idea what they are, but they appeared to get lost in the post so instead I bought some of these from a reputable place in the UK that come with a datasheet.
The next day, both items arrived together!
I'm trying to build a very simple proximity sensor for a robot, I built the following circuit:

simulate this circuit – Schematic created using CircuitLab
and stole this code to test it out:
#define IRledPin 8
#define D13ledPin 13
#define IRsensorPin 9

void IR38Write() {
  for(int i = 0; i <= 384; i++) {
    digitalWrite(IRledPin, HIGH);
    delayMicroseconds(13);
    digitalWrite(IRledPin, LOW);
    delayMicroseconds(13);
  }
}

void setup(){
  pinMode(IRledPin, OUTPUT);
  digitalWrite(IRledPin, LOW);
  pinMode(D13ledPin, OUTPUT);
  digitalWrite(D13ledPin, LOW);
}

void loop(){
  IR38Write();
  if (digitalRead(IRsensorPin)==LOW){
    digitalWrite(D13ledPin, HIGH);
  } else {
    digitalWrite(D13ledPin, LOW);
  }
}

If I hold my hand in front of it, nothing happens (LED on-board arduino should light up), however if I point a TV remote at it and press a button, the LED lights up. I tested 2 of the 'fancy' sensors that I got and both behaved the same.
Then I tried one of the 'lucky dip' sensors, swapped it straight in and the whole thing works perfectly - point a TV remote and the LED lights, hold my hand ~10cm in front of it and the LED lights!
So, where have I gone wrong?

@NickAlexeev - this is not actually an Arduino question, rather it revolves around the behavior of the IR receiver module.  Migrating it was improper - you have to read these things, not just trigger off of keywords.

I did wonder about that - this isn't really an Arduino-specific issue, it just happens that I'm using one in this instance.

What happens to these questions? Do they get migrated back to EE or just lost?

See page 5 of your datasheet - that 'fancy' sensor suppresses "• Continuous signals at any frequency".
So you'll need to pulse your 38.4kHz signal for the sensor to produce an output.

Wow, thanks. Datasheets are hard! It's actually quite hard to do that all on the same board - by the time the sensor starts looking for the signal, it's pretty much stopped bouncing back. I did manage to get it to trip with my hand by making it pulse but it's really unreliable. I chose entirely the wrong sensor for what I'm trying to do, I had no idea some were that clever! Thanks

You should be able to put a delay at the start of your loop, perhap 100ms, and adjust the number of cycles of output to be in range of what the detector considers a pulse.  It would be better if you checked for results while transmitting, subtracting the time to do so from the delays (probably use a scope to calibrate).  Or you can probably use a hardware timer to transmit.  Best proximity results will be with a synchronous detector, ie, lock-in amplifier rather than a remote receiver blob.

yes, perhaps you can use one of the PWM outputs on your arduino to drive the LED

The answer I've accepted is the correct answer, but I wanted to add this extra bit for completeness. I reworked my code to use non-blocking delays for the IR LED so the sensor actually gets a chance to see it before it stops transmitting and it works! Range is quite a bit shorter than the 'lucky dip' sensor (~ 2cm).
#define IR_LED 8
#define LED 13
#define SENSOR 9

unsigned long burst_timer;
unsigned long gap_timer;

unsigned long timestamp;

char led_state;
char burst_count;

const char BURST_MAX = 20;

void setup()
{
  pinMode(IR_LED, OUTPUT);
  led_state = LOW;
  burst_count = 0;
  digitalWrite(IR_LED, led_state);

  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);

  pinMode(SENSOR, INPUT);

  timestamp = micros();
  burst_timer = timestamp;
  gap_timer = timestamp;
}

void toggle_led()
{
  if (led_state == LOW)
  {
    led_state = HIGH;
  }
  else
  {
    led_state = LOW;
    burst_count++;
  }

  digitalWrite(IR_LED, led_state);
}

void loop()
{
  timestamp = micros();
  if (timestamp - burst_timer > 13 && burst_count < BURST_MAX)
  {
    toggle_led();
    burst_timer = timestamp;
    gap_timer = timestamp;
  }

  if (burst_count >= BURST_MAX && timestamp - gap_timer > (13*2*BURST_MAX) )
  {
    burst_count = 0;
    burst_timer = timestamp;
    gap_timer = timestamp;
  }

  if (digitalRead(SENSOR) == LOW)
  {
    digitalWrite(LED, HIGH);
  }
  else
  {
    digitalWrite(LED, LOW);
  }
}

Every time I use delay() (or delayMicroseconds()) I find a new reason not to!

That's a good lesson learned then. Delay() is second in line to String in the evil stakes.


text:
ATtiny85 Comparator C interrupt on timer 1
I have a program that uses Timer1 comparator A in CTC mode. I realize that I need to set OCR1C for the timer to reset at given value. However there is no such thing as an interrupt generated by timer1 counter matching OCR1C value.
Moreover, if I enable CTC and set for example OCR1A to 10, and OCR1C to 50, the interrupt handler ISR(TIMER1_COMPA_vect) will be triggered when the counter reaches OCR1C value, not OCR1A. I'm really confused...
Can anyone explain to me what's going on?
EDIT:
Here is the program that I'm using.
main program:

#include "avr/interrupt.h"

ISR (TIMER1_COMPA_vect) {
  PORTB ^= (1<<PB0); //toggle pin
}

void setup() {
  cli();
  // put your setup code here, to run once:
  //prescaler value 8192 sets one clock tick to about 1ms
  TCCR1 |= (1<<CS13)|(1<<CS12)|(1<<CS11)|(0<<CS10);
  //turn CTC mode on
  bitSet( TCCR1, CTC1 );
  //set comparatorA value
  OCR1A = 10;
  //enable compA interrupts
  bitSet(TIMSK, OCIE1A);
  //set comp C value
  OCR1C = 19;
  // initialize counter 1 on 0
  TCNT1 = 0;
  pinMode( 0, OUTPUT );
  digitalWrite( 0, HIGH );
  sei();
}

int main() {
  setup();
  // put your main code here, to run repeatedly:
  while(1) {
    }
 return 1;
}

You wrote “there is no such thing as an interrupt generated by timer1 counter matching OCR1C value”. Quoting the datasheet: “In PWM mode (either PWM1A=1 or PWM1B=1) the bit TOV1 is set (one) when compare match occurs between Timer/Counter1 and data value in OCR1C”. TOV1 is the flag that triggers the TIMER1_OVF interrupt. Note that you can enable PWM mode while keeping the PWM outputs disconnected from their pins (bits COM1xy cleared).

@EdgarBonet Alright, but in non-PWM mode theoretically matchA interrupt should be called whenever TCNT1 reaches OCR1A value, right? But this does not happend. In fact it is triggered only when it reaches OCR1C

I uploaded your program to an ATtiny25V (essentially a slower ATtiny85 with less memory) and I get exactly the expected behavior: a square wave on pin 0 with a period of roughly 328 ms. Note that the clock runs at 1 MHz, as the CKDIV8 fuse is programmed by default.

@EdgarBonet So you get a square wave that is high for OCR1A and low for OCR1C-OCR1A ticks?

I get 50% duty cycle, as expected from reading your code.

@EdgarBonet Ok so change the value of OCR1C to 50 and see if duty cycle changes

Did it. Period became 838 ms, duty cycle didn't change, just as expected.

@EdgarBonet But... it should change, right? Because only function that changes PB0 is ISR attached to matchA interrupt. For rest of time it should be LOW. When Counter1 reaches OCR1C, timer1 resets and whole thing starts over. If this is right, duty cycle shoulde definitly change. Correct me please if im wrong

Well, you are wrong. The only thing that changes PB0 is the ISR: every time the timer hits the OCR1A value, the pin toggles. When Counter 1 reaches OCR1C, timer1 resets and this has no effect whatsoever on PB0. If you want the timer to toggle a pin all by itself, you should use a PWM mode rather than an interrupt.

So if OCRC1A is 10 and OCRC1C is 50, pin toggles at 10, resets at 50, and then toggles at 10 etc... so duty cycle shoulde be 80% on one cycle and 20% at next. Right?

No. Pin toggles at 10, then pin toggles at 10, then pin toggles at 10... Duty cycles is 50%. Let me repeat it again: Timer 1 resetting has no effect whatsoever on PB0. Repeat: no effect whatsoever.

Let us continue this discussion in chat.