I am in between a small project using Arduino Uno R3 where i have to control a 9 X 16 LED Matrix.
Before i started the project i had planned for 8 X 8 LED Matrix (solution here would work for 8X8) and i know the same solution will work if I use a Arduino Mega (with more output pins)
Can any one suggest me how to control a 9 * 16 LED Matrix with Arduino UNO
You can drive up to 512 LEDs with some MAX7221 LED driver chips.
See here for instructions.
Another route to take would be to use multiplexers. They allow you to address many outputs (or inputs) with few arduino pins.
A setup similar to the one on the left would allow nesting of multiplexers to enable control of more LEDs. The only issue you would run into is that the LEDs may dim a little bit between being addressed.
Here's an Arduino page on the topic (with sample code). http://www.arduino.cc/playground/Learning/4051
/*
* codeexample for useing a 4051 * analog multiplexer / demultiplexer
* by david c. and tomek n.* for k3 / malm� h�gskola
*
* edited by Ross R.
*/
int r0 = 0; //value of select pin at the 4051 (s0)
int r1 = 0; //value of select pin at the 4051 (s1)
int r2 = 0; //value of select pin at the 4051 (s2)
int count = 0; //which y pin we are selecting
void setup(){
pinMode(2, OUTPUT); // s0
pinMode(3, OUTPUT); // s1
pinMode(4, OUTPUT); // s2
}
void loop () {
for (count=0; count<=7; count++) {
// select the bit
r0 = bitRead(count,0); // use this with arduino 0013 (and newer versions)
r1 = bitRead(count,1); // use this with arduino 0013 (and newer versions)
r2 = bitRead(count,2); // use this with arduino 0013 (and newer versions)
//r0 = count & 0x01; // old version of setting the bits
//r1 = (count>>1) & 0x01; // old version of setting the bits
//r2 = (count>>2) & 0x01; // old version of setting the bits
digitalWrite(2, r0);
digitalWrite(3, r1);
digitalWrite(4, r2);
//Either read or write the multiplexed pin here
}
}
Take a look at something like this: http://www.arduino.cc/playground/Learning/4051
Related
I made a nice code which generates fast PWM with 50% duty cycle and I can change the frequency with a potentiometer. It outputs straight and inverted channels with some dead time. I am using Arduino Micro aka ATmega32U4. The code is actually "Atmel" code. Code is working fine until I power Arduino Micro off and then on again.
I have programmed the code and registers so that the frequency is changeable from 10kHz to 100kHz. But after power on/off the frequency changes from 5kHz to 50kHz. After this has happened I have to program the board again using Arduino IDE, to make it work correctly. Again after power on/off it has changed. I am quite sure that one of the registers is overwritten by the "Arduino hardware abstraction layer" or however we should name it. I have not yet read out all the registers so I do not know which one is overwritten. I guess it's the prescaler.
How do I prevent this from happening? Should I write the register contents somewhere else? Or should I write it few times to be sure?
Why or how this is happening anyway?
Here's the code:
#define OSC1 5
#define OSC2 13
uint8_t read_reg1;
uint8_t read_reg2;
int pot, freq;
void setup() {
pinMode(OSC1, OUTPUT);
pinMode(OSC2, OUTPUT);
Serial.begin(9600);
cli(); // disable global interrupts
TCCR4A=0; // clear register
TCCR4B=0x06; // configure prescaler to 64 (CK = CLK / 64 = 1.5 MHz)
TCCR4C=0;
TCCR4D=0; // select Fast PWM operation (0 << WGM41)|(0 << WGM40)
PLLFRQ=(PLLFRQ&0xCF)|0x30; // select clock source and frequency
OCR4C=150; // select PWM frequency
OCR4A=150/2; // set duty cycle
DT4 = 0x55; // set dead times. DT = (1 / 48Mhz) * 0...15
// enable interrupt on timer4 overflow
TIMSK4|=(1 << TOIE4);
// This register write has to be after others. Otherwise the PWM generation will not work. I do not know why.
TCCR4A=0x42; // COM4A1..0 = 01, OC4A and !OC4A connected. PWM4A = 1 (activate channel A PWM output)
sei(); // enable global interrupts
}
void loop() {
//cli();
pot = analogRead(A0);
freq = map(pot, 0, 1023, 14, 166);
//sei();
/*
Serial.print("Pot value: ");
Serial.print(pot);
Serial.print("\tFreq value: ");
Serial.println(1500000/freq);
*/
}
ISR(TIMER4_OVF_vect){
OCR4C = freq;
OCR4A = freq / 2;
}
I am not sure exactly why you got different behavior right after programming, but the bootloader that the Arduino Micro uses (Caterina) does not perform a full reset after it runs, so changes that the bootloader made to the AVR's registers are often visible to the user's sketch.
I was able to fix the problem by removing the line that modifies PLLFRQ. Here is a simplified version of your code that always produces 3.31 kHz PWM:
void setup()
{
pinMode(5, OUTPUT);
pinMode(13, OUTPUT);
TCCR4A = 0;
TCCR4B = 0x06; // configure prescaler to 64 (CK = CLK / 64 = 1.5 MHz)
TCCR4C = 0;
TCCR4D = 0; // select Fast PWM operation (0 << WGM41)|(0 << WGM40)
OCR4C = 150; // select PWM frequency
OCR4A = 150 / 2; // set duty cycle
DT4 = 0x55; // set dead times. DT = (1 / 48Mhz) * 0...15
// This register write has to be after others.
// Otherwise the PWM generation will not work. I do not know why.
// COM4A1..0 = 01, OC4A and !OC4A connected.
// PWM4A = 1 (activate channel A PWM output)
TCCR4A = 0x42;
}
void loop()
{
}
It's not a great idea to mess with the PLL postscaler since it will probably affect every other Arduino library that uses timers, including the USB stack.
What I want: To connect a stand alone end device XBee in sleep mode to a XBee coordinator attached to a sparkfun redboard (Arduino Uno). For this example, I am using Faludis wireless sensor networks example on romantic lighting, but with the router/end device in sleep mode
When not in sleep mode, I have a light sensor hooked up to my end device, and sending via pin 20 to the coordinator radio. I have the coordinator pins 2 and 3 hooked up to the arduino board pin 0 and 1 respectively. My code for the coordinator arduino is from the book,
/*
* ROMANTIC LIGHTING SENSOR
*
* It detects whether your lighting is
* setting the right mood.
*
* USES PREVIOUSLY PAIRED XBEE ZB RADIOS
* by Rob Faludi http://faludi.com
*/
/*
CONFIGURATION
SENDER: (REMOTE SENSOR RADIO)
ATID3456 (PAN ID)
ATDH -> set to SH of partner radio
ATDL -> set to SL of partner radio
ATJV1 -> rejoin with coordinator on startup
ATD02 pin 0 in analog in mode
ATIR64 sample rate 100 millisecs (hex 64)
* THE LOCAL RADIO _MUST_ BE IN API MODE *
RECEIVER: (LOCAL RADIO)
ATID3456 (PAN ID)
ATDH -> set to SH of partner radio
ATDL -> set to SL of partner radio
*/
#define VERSION "1.02"
int LED = 11;
int debugLED = 13;
int analogValue = 0;
void setup() {
pinMode(LED, OUTPUT);
pinMode(debugLED, OUTPUT);
Serial.begin(9600);
}
void loop() {
// Make sure everything we need is in the buffer
if (Serial.available() >= 21) {
// Look for the start byte
if (Serial.read() == 0x7E) {
//Blink debug LED to indicate when data is received
digitalWrite(debugLED, HIGH);
delay(10);
digitalWrite(debugLED, LOW);
// Read the variables that we're not using out of the buffer
for (int i = 0; i<18; i++) {
byte discard = Serial.read();
}
int analogHigh = Serial.read();
int analogLow = Serial.read();
analogValue = analogLow + (analogHigh * 256);
}
}
/*
* The values in this section will probably
* need to be adjusted according to your
* photoresistor, ambient lighting, and tastes.
* For example, if you find that the darkness
* threshold is too dim, change the 350 value
* to a larger number.
*/
// Darkness is too creepy for romance
if (analogValue > 0 && analogValue <= 350) {
digitalWrite(LED, LOW);
}
// Medium light is the perfect mood for romance
if (analogValue > 350 && analogValue <= 750) {
digitalWrite(LED, HIGH);
}
// Bright light kills the romantic mood
if (analogValue > 750 && analogValue <= 1023) {
digitalWrite(LED, LOW);
}
//Serial.println(analogLow);
//Serial.println(analogHigh);
Serial.println(analogValue);
//delay(100);
}
Now when I change the settings on the router to end device, and
ATIR 3E8
ATSM 4
ATSP 64
ATST 14
I see the end device powering on every second (from LED's I have hooked to pins 13 15 and 6), but nothing on the coordinator end. Is there something I am doing wrong with the coordinator, or does the serial read on the Arduino just not like cyclic sleep mode?
I believe you need to tune your IR and SP settings. This Knowledge Base Article on Digi's site has a good explanation:
Example:Sample Rates work very well with cyclic sleep modes, since the
radio will sample once per wake period and immediately go back to
sleep. If more than one sample per wake period is required, then
modifications to the SO (Sleep Options) and ST (Time before Sleep)
parameter are needed.
I want to sample ADC1, DIO2, and DIO3 once every minute and send the
sample to a specific radio. To conserve battery life, the radio should
only sample once per wake period.
Configuration:
DH=0x0013A200
DL=0x12345678 (address of the collector node)
D1=0x02 (ADC)
D2=0x03 (Digital Input)
D3=0x03 (Digital Input)
IR=0x200 (512ms)
SM=0x04 (cyclic sleep)
SP=0x1770 (60 seconds)
With this configuration, the radio will wake once every minute, sample
D1 as an ADC, D2 and D3 as Digital Inputs, and send the single sample
to the radio with the address 0013A200 12345678 before going back to
sleep. The IR parameter does not exceed the radio’s wake period (this
varies depending on the radio, but with the default settings it will
only be a few milliseconds) so only one sample will be taken and sent
over-the-air once per minute as defined by the sleep period instead of
the sample rate interval.
I have this RFID reader "Rosslare AY-X12", and it's working with Wiegand 26bit. I have an arduino mini Pro and connected together it's working fine but it only reads the card one time and then I have nothing.
When I put on the card arduino reads that card but only one time during the card is near by the reader and it again reads that card when I put off the card and then I put on. But I want to read that card continuously, I mean when the card is near by the Reader still reading the card, every 1ms reads that card.
Do you have any idea how to do that ? Is there any RFID arduino library which can do that? I had got the Mifare and its can do that. But this 125Khz reader which can communicate over Wiegand can't do that or I don't know how to do that.
I'm using this library : https://github.com/monkeyboard/Wiegand-Protocol-Library-for-Arduino
My previous answer was deleted. I am going to make another attempt to answer the questions.
Do you have any idea how to do that ?
This cannot be done by Arduino because Arduino in your case is just reading the D0 and D1 pulses from your RFID reader. Since your RFID reader Rosslare AY-X12 does not send out continuous output of wiegand protocol, there is no way Arduino can read more than what was not sent to it.
The common RFID readers will not send continuous data of the same card because in the common use case (entry/exit/attendance), normally one tap is to check-in and another tap is to check-out. If the RFID reader sends continuous data of the same card, the main system receiving the multiple wiegand data will be confused and will not be able to determine if the user actually wish to check-in or check-out.
Is there any RFID arduino library which can do that?
No. There is no such RFID Arduino library. If the RFID reader is not sending out continuous data, there is no way the receiver (Arduino) can receive them.
Is there a way to achieve this?
Yes, there are some readers that has the option to turn on the continuous output of data, for example 714-52 Mifare® ID Reader with selectable outputs. In its specification :
Continuous output with tag in field or single transmission
With this reader configured to continuous output, you can then use Arduino and the monkeyboard wiegand library to read the data.
I wrote my own wiegand code. Its not that difficult. I attached interrupts to the data pins and when they change I log the zero or one. You then build up the binary string and once timed out because no bits coming in. Then you convert the binary to decimal.
#include <LiquidCrystal.h>
int data0 = 2; //set wiegand data 0 pin
int data1 = 3; //set wiegand data 1 pin
unsigned long bit_holder; //unsigned long (positive 32 bit number)
unsigned long oldbit = 0;
volatile int bit_count = 0;
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
unsigned long badge;
unsigned int timeout;
unsigned int t = 800;
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
lcd.print("Present Badge");
delay(2);
Serial.println("Present Badge");
pinMode(data0, INPUT);
digitalWrite(data0, HIGH);
pinMode(data1, INPUT);
digitalWrite(data1, HIGH);
attachInterrupt(0, zero, FALLING); //attach interrupts and assign functions
attachInterrupt(1, one, FALLING);
}
void zero(){
bit_count ++;
bit_holder = (bit_holder << 1) + 0; //shift left one and add a 0
timeout = t;
}
void one(){
bit_count ++;
bit_holder = (bit_holder << 1) + 1; //shift left one and add a 1
timeout = t;
}
void loop() {
timeout --;
if (timeout == 0 && bit_count > 0){
lcd.clear();
lcd.print("Dec:");
lcd.print(bit_holder);
lcd.setCursor(0,1);
lcd.print("Hex:");
lcd.print(String(bit_holder,HEX));
Serial.print("bit count= ");
Serial.println(bit_count);
Serial.print("bits= ");
Serial.println(bit_holder,BIN);
oldbit = bit_holder; //store previous this value as previous
bit_count = 0; //reset bit count
bit_holder = 0; //reset badge number
}
}
You may need to find a reader that offer a continuously reading, as I know almost of Wiegand Reader in the market can't perform a continuously reading because they have a "onboard" control that controls this...
Maybe you can try with Arduino Serial RFID Reader...
try a this timer libary Timer1 and mayby try this code it worked for me, my tags and cards now reads continuously.
Greetings from Denmark
Gregor
#include <Timer1.h>
//******************************************************************
// ATmega168, ATmega328:
// - Using Timer 1 disables PWM (analogWrite) on pins 9 and 10
// ATmega2560:
// - Using Timer 1 disables PWM (analogWrite) on pins 11 and 12
// - Using Timer 3 disables PWM (analogWrite) on pins 2, 3 and 5
// - Using Timer 4 disables PWM (analogWrite) on pins 6, 7 and 8
// - Using Timer 5 disables PWM (analogWrite) on pins 44, 45 and 46
//******************************************************************
unsigned int lastTime;
#include <SoftwareSerial.h>
SoftwareSerial RFID = SoftwareSerial(2,4);
char character;
String our_id;
void setup()
{
// Disable Arduino's default millisecond counter (from now on, millis(), micros(),
// delay() and delayMicroseconds() will not work)
disableMillis();
// Prepare Timer1 to count
// On 16 MHz Arduino boards, this function has a resolution of 4us
// On 8 MHz Arduino boards, this function has a resolution of 8us
startCountingTimer1();
lastTime = readTimer1();
Serial.begin(9600);
RFID.begin(9600);
}
void loop()
{
unsigned int now = readTimer1();
while (RFID.available()>0)
{
character = RFID.read();
our_id += character;
lastTime = now;
}
if (our_id.length() > 10) {
our_id = our_id.substring(1,13);
Serial.println(our_id);
our_id = "";
}
delay(1000);
}
I am using an Arduino board to read out the value of a soft potmeter. (a strip that detects touch). This works perfectly fine as long as the strip is being touched (a resistance is added to the current).
When the strip is not touched, a completely random floating number is read by the analog pin. Forums mention that you have to add a pullup/pulldown resistor to cancel this effect, but this does not seem te be working. What is wrong with this code?
int potPin = 2;
int curval = 0;
// detect potmeter value
void setup() {
//enable pullup resistor, but still results in erratic output
//when potmeter is not touched
digitalWrite(potPin, HIGH);
//write to serial
Serial.begin(9600);
}
void loop() {
curval = analogRead(potPin);
// this works when the potmeter is being pressed (displays 0 to 1024)
Serial.println(curval);
delay(150);
}
Change
int potPin = 2;
to
int potPin = A2;
Your original use of "2" in both places is assigning Digital Pin 2 to pull-up and reading from Analog Channel 2. As "2" maps correspondingly to is PortD bit 2 and Analog Channel 2 (aka ADC2) is PortC bit 2. As shown below
digitalWrite(2, HIGH); // Pin D2
curval = analogRead(2); // AMUX Channel 2
where A2 shown below is interpreted as follows
digitalWrite(A2, HIGH); // Pin (A2 aka D16)
curval = analogRead(A2); // AMUX Channel 2 on Pin A2
On an UNO (ATmega328) the analogRead() function will interpret 0-7 as channels and will convert the pins A0 through A7 (D14-D21) to corresponding channels, to read from.
Note:
ADC6 and 7 are not available on the chip used on the UNO.
A0-A7 are alias for Digital 14 through 21. Where the labels A0-A7 are typically used.
I'm a newcomer to Arduino, and I'm trying to use Processing to control my Arduino Uno board relying on Firmata library. However after quick test, I can't seem to be able to light up my LED when using analog pins from A0 to A5, while it works without any problem for digital pins 0 - 13. Using Arduino directly works without any issue for all 19 pins.
void setup() {
arduino = new Arduino(this, "/dev/tty.usbmodem1411" );
for( int i = 0; i < 20; i++ ) // in Arduino A0 is pin 14, but to be sure I also tried in processing pin 16, just in case if A0 is 0xA0
arduino.pinMode( i, Arduino.OUTPUT );
}
void draw() {
for( int i = 0; i < 20; i++ ) { // quick and dirty mode to test all LEDs
arduino.digitalWrite( i, Arduino.HIGH );
arduino.analogWrite( i, 255 );
}
}
Currently I'm using SainSmart UNO board, and the reason I'm using processing because I need to access higher level libraries which are only available at processing for now.
Does anyone know how to code so that I can use Processing to access the analog pins on the Arduino board ?
It might be good idea to turn Analog Inputs as INPUTS in Firmata sketch inside Arduino.
void setup()
{
pinMode(A0, OUTPUT); // <- like this...
Firmata.setFirmwareVersion(0, 1); //... and then go on with standard firmata
Firmata.begin();
}