Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

(solved)Trouble making 8x8 matrix with timelapse

Status
Not open for further replies.

fezder

Well-Known Member
Right, so far i've managed to create with your help scrolling display, as well as many other things. Recently i learned that array can be used also to store data from ADC. But, what i'm now trying to create (seems my brains need constantly something new to be learned....) is that 8x8 matrix would show data from ADC in timelapse, like take reading from ADC->store in array one by one-> display in matrix one by one (in either bar or dot mode,). What makes it also hardish, is that value will change all the time, so effect would look roughly same like in roll-mode on oscilloscope.
Stuff, bits'n pieces i have so far:
First code i have taking data and storing it in array

C:
const unsigned int numReadings = 8;          //matrix is 8-wide
unsigned int analogvals[numReadings];       //array where to store 8-readings from ADC
unsigned int i = 0;

void setup()
{
  Serial.begin(9600);    //open serial
}

void loop()
{
  analogvals[i] = analogRead(A0);
  i++;
  if (i>=numReadings)
  {
    i=0; //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
  }
  delay(100); //wait 1 sec                      //from here on, print values from array one by one when called
  Serial.println(analogvals[0]);
   delay(100); //wait 1 sec
  Serial.println(analogvals[1]);
   delay(100); //wait 1 sec
  Serial.println(analogvals[2]);
   delay(100); //wait 1 sec
  Serial.println(analogvals[3]);
   delay(100); //wait 1 sec
  Serial.println(analogvals[4]);
   delay(100); //wait 1 sec
  Serial.println(analogvals[5]);
   delay(100); //wait 1 sec
  Serial.println(analogvals[6]);
   delay(100); //wait 1 sec
  Serial.println(analogvals[7]);
}

Then code i can use for creating bar/dot graph in matrix
C:
int dataPin = 2;        //  ic: 14, ser_in Define which pins will be used for the Shift Register control
int latchPin = 3;      //   ic:12         silkscreen numbers!
int clockPin = 4;      //   ic:11
int i = 0;
//OE-GND (PIN 13)
//MR-VCC (PIN 10)
byte mappedValue[9] = {0, 1, 3, 7, 15, 31, 63, 127}; //bar mode
byte mappedValue2[9] = {0, 1, 2, 4, 8, 16, 32, 64, 127}; //dot mode


void setup()
{
  DDRD = DDRD | B11111100;  //port registers used to set pin directions
}

void loop()
{
      i++;
  if (i >= 8)
  {
  i = 0;    //so bits aren't losed
  }
  int j = map( analogRead (A0), 0, 1023, 0, 8 );  //read and map
  j = mappedValue[j]; //convert mapped value to byte array

  PORTD = B00001000; //close latch pin
  shiftOut(dataPin, clockPin, MSBFIRST, 1<<i);  //only one column active at a time
  shiftOut(dataPin, clockPin, MSBFIRST, j);     //draw bars
  PORTD = B00000000;  //open latch pin


}

and lastly, code for scrolling
C:
int dataPin = 2;        //IC 14       //Define which pins will be used for the Shift Register control
int latchPin = 3;       //IC 12
int clockPin = 4;       //IC 11
//OE-GND
//MR-VCC
int delaytime = 1, timer, timerPrev = 0;
int shift = 0;
int len = 32;
static uint8_t  x [32] =
{
  B00000000,
  B00000000,
  B01111110,
  B00001000,              
  B01111110,
  B00000000,
  B01111110,
  B01001010,

  B01000010,
  B00000000,
  B01111110,
  B00000010,
  B00000000,
  B01111110,
  B00000010,
  B00000000,

  B00111100,
  B01000010,
  B00111100,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000,

  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000,
};



void setup()
{
  DDRD = DDRD | B00011100;                                  //set pins as output

}

void loop()
{
  timer = millis ();
  if (timer-timerPrev >100)
  {
    shift++;
    if(shift==len)shift=0;
    timerPrev=timer;
  }
       for(int i=0; i<8; i++)               
      {
        PORTD = B00000000;                                  //turn latch low
        shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);          //Send the data #2        (what columns to power)
        shiftOut(dataPin, clockPin, LSBFIRST, x[i+shift > len-1 ? i+shift-len : i+shift]);          //Send the data #1       ( what data to draw)
        PORTD = B00001000;                                  //turn latch on->show screen
        delayMicroseconds (1000);
      }


}
I have feeling that switch case is needed to change that value from array used for storing ADC data, but again, help would be great! or hints/clues, just trying to learn and making something useful on way :). And still using chained 74595 shift registers, two pieces in this circuit, plus darlington array for columns
 
Last edited:
managed to somewhat fill matrix with arrays values, but there are still two things bothering: output is not bar/dot (haven't mapped them, probadly some switch case-thingy) and display updates way too fast to serve as timelapse
C:
int dataPin = 2;        //IC 14       //Define which pins will be used for the Shift Register control
int latchPin = 3;       //IC 12
int clockPin = 4;       //IC 11
//OE-GND
//MR-VCC
int delaytime = 1, timer, timerPrev = 0;
int shift = 0;
int len = 8;
const unsigned int numReadings = 8;          //matrix is 8-wide
unsigned int  x[8];
unsigned int i = 0;
unsigned int y = 0;




void setup()
{
  DDRD = DDRD | B00011100;                                  //set pins as output

}

void loop()
{
  x[y] = analogRead(A0);
  y++;
  if (y>=numReadings)
  {
    y=0; //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
  }
  timer = millis ();
  if (timer - timerPrev > 100)
  {
    shift++;
    if (shift == len)shift = 0;
    timerPrev = timer;
  }
  for (int i = 0; i < 8; i++)
  {
    PORTD = B00000000;                                  //turn latch low
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);          //Send the data #2        (what columns to power)
    shiftOut(dataPin, clockPin, LSBFIRST, x[i + shift > len - 1 ? i + shift - len : i + shift]); //Send the data #1       ( what data to draw)
    PORTD = B00001000;                                  //turn latch on->show screen
    delayMicroseconds (1000);
  }


}
 
Last edited:
I found that writing to matrices is easier once its set up like a linear array...

Did you see my setup for using 8 8x8 matrix It was 32x16 dot screen!! So I treated like a Toshiba T6963C style screen ( albeit a bit smaller ).... Works very well because you can use graphics and fonts quite easily...

If you set up the matrices as you have done, you need to sort the timing out every time you change the code....

I use interrupts to keep the LED's up to date and write to an off screen buffer!!!
 
Did you see my setup for using 8 8x8 matrix It was 32x16 dot screen!!
i did see one your video where there was also 7-segment displays counting alongisde matrises. Looked cool!
I use interrupts to keep the LED's up to date and write to an off screen buffer!!!
So, buffer/array gets filled and interrupt (timer) handles when to update display?
and since i want bar/dot display, i suppose buffer is filled with those values, or what would be best approach?
 
Imagine you have a "software driver" to update the LED's as if it were a 16x32 pixel screen..

The functions would be putpixel, line, circle, text, etc.... You could write to the LED's how you want!!!

I am off work until Monday..... I wouldn't be able to do anything for the first couple of days as my workshop is in Rochdale.... As the floor was covered in a foot of water over the Christmas period there is a bit of a clean up to do!!

At least two computers are making funny noises and I'll need to replace them... I have an Arduino setup at work so I'll try and port the code to the Arduino so you have a base to start with!!!
 
I am off work until Monday..... I wouldn't be able to do anything for the first couple of days as my workshop is in Rochdale.... As the floor was covered in a foot of water over the Christmas period there is a bit of a clean up to do!!
ew, talk about leakage...hopefully nothing permament damage came

managed to somewhat do progress, array indeed stores mapped values, they can be seen if potentiometer is swinged fast enough. That said, also update speed is screwed and change can happen anywhere during array-loading....but still, small progress :)

thanks for helping out Ian!
C:
int dataPin = 2;        //  ic: 14, ser_in Define which pins will be used for the Shift Register control
int latchPin = 3;      //   ic:12         silkscreen numbers!
int clockPin = 4;      //   ic:11

const unsigned int numReadings = 8;          //matrix is 8-wide
unsigned int analogvals[numReadings];       //array where to store 8-readings from ADC
unsigned int i = 0;
unsigned int array[8];   //array where to store mapped values from ADC
byte mappedValue[9] = {0, 1, 3, 7, 15, 31, 63, 127}; //bar mode

void setup()
{
  DDRD = DDRD | B11111100;  //port registers used to set pin directions
}

void loop()
{

  int j = map( analogRead (A0), 0, 1023, 0, 8 );  //read and map
  j = mappedValue[j]; //convert mapped value to byte array
  //analogvals[i] = j;   //array where to store direct values from ADC
  array[i]=j;          //array where to store mapped values, taken from mappedValue array
  i++;                  //increment what array to read/write
  if (i>=numReadings)
  {
    i=0; //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
  }
     
    PORTD = B00001000; //close latch pin
  shiftOut(dataPin, clockPin, MSBFIRST, 1<<i);         //what column to power, only one active/time
  shiftOut(dataPin, clockPin, MSBFIRST, array[i]);     //data itself shown, taken from array where stored the mapped values
  PORTD = B00000000;  //open latch pin
          delay(5);

}
 
Last edited:
ew, talk about leakage...hopefully nothing permanent damage came
Rochdale has been hit by flooding.... Rochdale is so named as it's on the river Roch!! The persistent rain here has caused mayhem!!
 
for some reason ''Rochdale'' remined me from Rochard, some character and indeed, it was in movie ''watchmen''
Btw, managed to make code that allows to scroll (more like show) numbers with potentiometer, like voltmeter:
and with small change whole array can be checked with potentiometer, this should come handy someday
C:
/*
remember resistors for display, if needed
4543               uno         7-segment      uln2003
                                  D4             11
                                  D3             12
                                  D2             11
                                  D1             10
                                                 8-GND
                   8                             7
                   9                             6
                   10                            5
                   11                            4

1-vcc
2----------------7
3----------------6
4----------------5
5----------------4
6-gnd
7-gnd
8-gnd
9------------------------------A
10-----------------------------B
11-----------------------------C
12-----------------------------D
13-----------------------------E
14-----------------------------G
15-----------------------------F
16-GND
*/

int dataPin = 2;        //IC 14       //Define which pins will be used for the Shift Register control
int latchPin = 3;       //IC 12
int clockPin = 4;       //IC 11


int i = 0;
int const t = 1;
int val;

static uint8_t  x [400] =
{
  0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff, // square
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // block
  0x00, 0x7c, 0xa2, 0x92, 0x8a, 0x7c, 0x00, 0x00, // 0
  0x00, 0x42, 0xfe, 0x02, 0x00, 0x00, 0x00, 0x00, // 1
  0x00, 0x42, 0x86, 0x8a, 0x92, 0x62, 0x00, 0x00, // 2
  0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 3
  0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 4
  0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 5
  0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 6
  0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 7
  0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 8
  0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 9
  0x00, 0x7e, 0x90, 0x90, 0x90, 0x7e, 0x00, 0x00, //A
  0x00, 0x7e, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, //B
  B00000000, B01111100, B10000010, B10000010, B10000010, B01000100, B00000000, B00000000, //C
  B00000000, B11111110, B10000010, B10000010, B10000010, B01111100, B00000000, B00000000, //D
  B00000000, B11111110, B10010010, B10010010, B10010010, B10000010, B00000000, B00000000, //E
  B00000000, B11111110, B10010000, B10010000, B10010000, B10000000, B00000000, B00000000, //F
  B00000000, B01111100, B10000010, B10001010, B10001010, B01001100, B00000000, B00000000, //G
  B00000000, B11111110, B00010000, B00010000, B00010000, B11111110, B00000000, B00000000, //H
  B00000000, B00000000, B10000010, B11111110, B10000010, B00000000, B00000000, B00000000, //I
  B00000000, B00001100, B00000010, B00000010, B00000010, B11111100, B00000000, B00000000, //J
  B00000000, B11111110, B00010000, B00101000, B01000100, B10000010, B00000000, B00000000, //K
  B00000000, B11111110, B00000010, B00000010, B00000010, B00000010, B00000000, B00000000, //L
  B00000000, B11111110, B01000000, B00100000, B01000000, B11111110, B00000000, B00000000, //M
  B00000000, B11111110, B00100000, B00010000, B00001000, B11111110, B00000000, B00000000, //N
  B00000000, B01111100, B10000010, B10000010, B10000010, B01111100, B00000000, B00000000, //O
  B00000000, B11111110, B10010000, B10010000, B10010000, B01100000, B00000000, B00000000, //P
  B00000000, B01111100, B10000010, B10001010, B10000110, B01111110, B00000000, B00000000, //Q
  B00000000, B01111110, B10010000, B10011000, B10010100, B01100010, B00000000, B00000000, //R
  B00000000, B01100100, B10010010, B10010010, B10010010, B01001100, B00000000, B00000000, //S
  B00000000, B10000000, B10000000, B11111110, B10000000, B10000000, B00000000, B00000000, //T
  B00000000, B11111100, B00000010, B00000010, B00000010, B11111100, B00000000, B00000000, //U
  B00000000, B11111000, B00000100, B00000010, B00000100, B11111000, B00000000, B00000000, //V
  B00000000, B11111110, B00000100, B00001000, B00000100, B11111110, B00000000, B00000000, //W
  B00000000, B11000110, B00101000, B00010000, B00101000, B11000110, B00000000, B00000000, //X
  B00000000, B11000000, B00100000, B00011110, B00100000, B11000000, B00000000, B00000000, //Y
  B00000000, B10000110, B10001010, B10010010, B10100010, B11000010, B00000000, B00000000, //Z
  B00000000, B01000000, B10000000, B10001010, B10010000, B01100000, B00000000, B00000000, //?
  B00000000, B00000000, B00000000, B11111010, B00000000, B00000000, B00000000, B00000000, //!
  B00000000, B00010000, B00010000, B01111100, B00010000, B00010000, B00000000, B00000000, //+
  B00000000, B00010000, B00010000, B00010000, B00010000, B00010000, B00000000, B00000000, //-
  B00000000, B00101000, B00101000, B00101000, B00101000, B00101000, B00000000, B00000000, //=
  B00000000, B00000000, B00000000, B01111100, B10000010, B00000000, B00000000, B00000000, //(
  B00000000, B00000000, B10000010, B01111100, B00000000, B00000000, B00000000, B00000000, //)

};


void setup()
{
  DDRD = DDRD | B00011100;                                  //set pins as output
}

void loop()
{
  i++;
  if (i > 8)
  {
    i = 0;
  }
  val = analogRead (A0);
  PORTD = B00000000;                 //display 0
  shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);        //Send the data #2        (what columns to power)
  picknumber(val * 10 / 1000 % 10);
  PORTD = B00001000;                 //display 0
  delay(t);

}





void picknumber( int count)      //pick numbers from array, at start of whole code
{
  switch (count)
  {
    case 0: shiftOut(dataPin, clockPin, LSBFIRST, x[i + 16]); break;          //0
    case 1: shiftOut(dataPin, clockPin, LSBFIRST, x[i + 24]); break;          //1
    case 2: shiftOut(dataPin, clockPin, LSBFIRST, x[i + 32]); break;         //2
    case 3: shiftOut(dataPin, clockPin, LSBFIRST, x[i + 40]); break;         //3
    case 4: shiftOut(dataPin, clockPin, LSBFIRST, x[i + 48]); break;         //4
    case 5: shiftOut(dataPin, clockPin, LSBFIRST, x[i + 56]); break;         //5
    case 6: shiftOut(dataPin, clockPin, LSBFIRST, x[i + 64]); break;         //6
    case 7: shiftOut(dataPin, clockPin, LSBFIRST, x[i + 72]); break;         //7
    case 8: shiftOut(dataPin, clockPin, LSBFIRST, x[i + 80]); break;         //8
    case 9: shiftOut(dataPin, clockPin, LSBFIRST, x[i + 88]); break;         //9
  }
}
 
Last edited:
So far better code, now screen shows values that are readable. Only issues are that matrix can show new values anywhere, not just other end of corner. Other issue is that the end where scrolling starts, has brighter leds than rest of matrix. But, still slight progress IMO:
EDIT:typos
C:
int dataPin = 2;        //IC 14       //Define which pins will be used for the Shift Register control
int latchPin = 3;       //IC 12
int clockPin = 4;       //IC 11
                        //OE-GND, can show mumbo-jumbo at beginning, but no issue
                        //MR-VCC
int delaytime = 1, timer, timerPrev = 0;
int shift = 0;
int len = 8;
static uint8_t  x [8];
int m;
const unsigned int numReadings = 8;          //matrix is 8-wide, 8 readings is enough
unsigned int analogvals[numReadings];       //array where to store 8-readings from ADC
unsigned int i = 0;
byte mappedValue[8] = {0, 1, 3, 7, 15, 31, 63, 127}; //bar mode



void setup()                  //setup, runs once
{
  DDRD = DDRD | B00011100;    //set pins as output (
  noInterrupts();
  TCCR1A = 0;
  TCCR1B = 0;             
  TCNT1 = 0;               
  OCR1A = 34286;              //compare register
  TCCR1B |= (1 << WGM12);     // CTC mode, clear when compare matches
  TCCR1B |= (0 << CS10);      // 8 prescale
  TCCR1B |= (1 << CS11);      // 8 prescale
  TCCR1B |= (0 << CS12);      // 8 prescale
  TIMSK1 |= (1 << OCIE1A);    //enable timer compare interrupt
  interrupts();
}

void loop()                        //loop that takes care of loading the array as well as mapping
{
  int j = map( analogRead (A0), 0, 1023, 0, 8 );  //read and map
  j = mappedValue[j];                             //convert mapped value to byte array
  x[m] = j;                                       //array where to store mapped values, taken from mappedValue array
  m++;                                            //increment what array to read/write
  if (m >= numReadings)
  {
    m = 0;                                        //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
  }
  delay(100);                                     //10 samples per second
}

ISR(TIMER1_COMPA_vect)              //ISR, refresh screen
{
  timer = millis ();
  if (timer - timerPrev > 200)
  {
    shift++;
    if (shift == len)shift = 0;
    timerPrev = timer;
  }
  for (int i = 0; i < 8; i++)                               //counter for columns
  {
    PORTD = B00000000;                                      //turn latch low
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);          //(what columns to power)
    shiftOut(dataPin, clockPin, LSBFIRST, x[i]); //(what data to draw)
    PORTD = B00001000;                                      //turn latch on->show screen
    delayMicroseconds(1000);                                //is this unnecessary?  matrix behaves better, but inside ISR delays should be avoided yes?
  }
}
 
Last edited:
OK, people at arduino forums helped out also, here's code that is currently working but please, tell your opinions! this is cinda confusing code for me to read to be honest -_-
C:
const int DATA_PIN = 2;       //  ic: 14, ser_in Define which pins will be used for the Shift Register control
const int LATCH_PIN = 3;      //   ic:12         silkscreen numbers!
const int CLOCK_PIN = 4;      //   ic:11
const byte END_DATA_MARKER = 9;
const boolean TEST_MODE_FLAG = 1;
const boolean DEFAULT_REVERSE_FLAG = 0;
const byte NUMBER_OF_READINGS = 8;          //matrix is 8-wide
const byte MAX_COLUMN_INDEX = NUMBER_OF_READINGS - 1;
unsigned int analogvals[NUMBER_OF_READINGS];       //array where to store 8-readings from ADC
unsigned int pixelArray[8];   //array where to store mapped values from ADC
byte solidLedColumn[9] = {0, 1, 3, 7, 15, 31, 63, 127}; // was "mappedValue" //bar mode
byte testData[] = {0, 1, 3, 4, 3, 5, 4, 3, 6, 6, 7, 8, 8, 7, 5, 3, 4, 3, 2, 1, 0, END_DATA_MARKER};
byte testDataIndex = 0;
byte columnCount = 0;
byte activeColumn = 0;
const unsigned int SPEED_OPTIONS = 8;
const unsigned int MAX_SPEED = SPEED_OPTIONS - 1;
const int DEFAULT_SPEED = SPEED_OPTIONS / 2;
const unsigned int REFRESH_CYCLES_AT_LOWEST_SPEED = 1000;
const unsigned int REFRESH_CYCLES_AT_HIGHEST_SPEED = 20;
const unsigned long VERY_SHORT_PAUSE = 100;
unsigned int speedToCyclesTable[SPEED_OPTIONS];
unsigned int cyclesToUpdate;

void setup()
{
  fillTable();
  cyclesToUpdate = speedToCyclesTable[DEFAULT_SPEED];
  DDRD = DDRD | B11111100;  //port registers used to set pin directions
}

void loop()
{
  byte activeLeds;
  if (TEST_MODE_FLAG)
  {
    if (testData[testDataIndex] == END_DATA_MARKER)
    {
      testDataIndex = 0;
    }
    activeLeds = testData[testDataIndex++];
  }
  else
  {
    activeLeds = map( analogRead (A0), 0, 1023, 0, 8 );  //read and map
  }

  if (activeColumn == MAX_COLUMN_INDEX)
  {
    shiftArray(DEFAULT_REVERSE_FLAG);
  }

  pixelArray[activeColumn] = solidLedColumn[activeLeds];

  cycleLeds(cyclesToUpdate);

  columnCount++;
  activeColumn = constrain(activeColumn + 1, 0, MAX_COLUMN_INDEX);
}

void cycleLeds(unsigned int cycles)
{
  for (int i = 0; i < cycles; i++)
  {
    for (int j = 0; j < NUMBER_OF_READINGS; j++)
    {
      PORTD = B00001000; //close latch pin
      shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, 1 << j);       //what column to power, only one active/time
      shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, pixelArray[j]);     //data itself shown, taken from array where stored the mapped values
      PORTD = B00000000;  //open latch pin
      delayMicroseconds(VERY_SHORT_PAUSE);
    }
  }
}

void shiftArray(boolean reverseFlag)
{
  if (reverseFlag)
  {
    for (int i = NUMBER_OF_READINGS - 1; i > 0 ; i--)
    {
      pixelArray[i] = pixelArray[i - 1];
    }
    pixelArray[0] = 0;
  }
  else
  {
    for (int i = 0; i < NUMBER_OF_READINGS - 1; i++)
    {
      pixelArray[i] = pixelArray[i + 1];
    }
    pixelArray[NUMBER_OF_READINGS - 1] = 0;
  }
}

void fillTable()
{
  unsigned int cyclesRange = 1 + REFRESH_CYCLES_AT_HIGHEST_SPEED - REFRESH_CYCLES_AT_HIGHEST_SPEED;

  for (int i = 0; i < SPEED_OPTIONS; i++)
  {
    speedToCyclesTable[i] = REFRESH_CYCLES_AT_HIGHEST_SPEED + (i * cyclesRange / MAX_SPEED);
  }
}
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top