#include #include static inline void errBlinky(uint16_t repeat); /* Qualcomm AR9271 802.11n chip needs firmware from the manufacturer, but they * are not capable of producing reliable software. During normal use they * require their chip to be reset for continued operation. * * There is no documentation on when one might need to perform this reset. * Based on some observation I found that the both chip and firmware support * controlling a LED from the USB host. When the manufacturer's firmware is * requiring the host to perform the reset controlling the LEDs does not work * as expected, indicating the request for reset. * * Yes, I understand how dumb this is, but one must understand the situation * that Qualcomm is in. If they knew what they were doing things would be * different, and that, might cause them some concern. * * -- * * Monitor the LED output, the host should blink the LED once per second. We * will blink our LED in sync with their LED and blink rapidly if we are * resetting the AR9271. */ int main(void) { // Set our led to output DDRB |= _BV(PB5); // Set input (pin labeled 12), connect this to the AR9271 LED output DDRB &= ~_BV(PB4); uint8_t last = 0; uint8_t count = 0; for(;;) { uint8_t status = 0; // host must keep the LED on for a minimum of one second per Nyquist-Shannon Sampling Theorem for(uint8_t i = 10; i--;) { // mirror our led to the AR9271 led, and remember it's status if(status = (PINB & _BV(PB4))) PORTB |= _BV(PB5); else PORTB &= ~_BV(PB5); // do this over about 500ms (one half second, we are in a fixed length loop) _delay_ms(50); } // compare the recorded state to the last state, it should alternate if(++count && last != status) count = 0; // stash status to compare next time... last = status; // if the counter is small we can skip reset if(3 >= count) continue; else count = 0; // power off USB device { // switch outputs to high impedance rather than "turning off", same effect DDRB &= ~ (_BV(PB2) | _BV(PB3)); // wait three seconds (50 thousandths of a minute) errBlinky(50); } // power on USB device, computer will load firmware into it { // Set relay (pins labeled 10 and 11) to output. DDRB |= (_BV(PB2) | _BV(PB3)); // [!] Use digital pins as power source, relay coil should be >200 Ohms PORTB |= _BV(PB2); PORTB &= ~_BV(PB3); // let the relay pull in, click, clack, and whatever _delay_ms(100); // drop power consumption (switch pin 11 to high impedance) DDRB &= ~_BV(PB3); // failure after power-up is unlikely, should consider computer boot time errBlinky(3000 /* thousandths of a minute is three minutes */); } } return 0; } static inline void errBlinky(uint16_t repeat) { // limit repeat to a maximum of about three minutes repeat = (3000 < repeat) ?3000 :repeat; // alternate our led every one thousandths of a minute to show error state for(;repeat--;) { PORTB ^= _BV(PB5); _delay_ms(60); } } /* some numbers regarding the relay and our arduino pro mini * we are using a 3V3 Pro Mini connected to a Omron G6DS-1A-H5 * the relay says it must switch at 70% of rated 5V, which is 3V5 so we * are under powering the relay, cross your fingers * * the relay datasheet claims an operate time of 10ms max, so when we switch * it 100ms is plenty for debounce. We will also pull back the current using * a current limit resistor, the datasheet claims 5% of rated voltage for must * release. We use a 200 Ohm resistor and the coil is 208 Ohm. We might push * about 8mA current with our 3V3 digital pin, so that'll be interesting if * that works. * * [?] attempting to power the relay with a diode on PB3 and a resistor on * PB2 was not enough, using a test PSU 3V0 is enough to energize relay, but * it was right on the edge. I ended up putting a PNP transistor on PB3 with * it's emitter on the 5V rail, this is more than enough. Code obviously needs * to be adjusted because we want PB3 and PB2 to oppose each other. The Zener * is used to make sure that when PB3 floats it isn't pulled to 3V3 by the * 328p digital input pin proection diodes. 2V1 seemed to be enough, more is * fine, but when PB3 is driven to ground the base of the PNP does need to come * down a bit less than the 5V so 4V2 might be the limit on the Zener or the relay * may not energize. I did test with two series silicon diodes with the opposite * polarity hoping the 1V2 forward voltage was enough to let the base float to 5V * but it did not work. * * * Arduino 3V3 Pro Mini * +---------------+ * | o o o o o o | ___ * |o o| -------|___> 5V * |o _ _ o| -----+ * |o | | | | o| | * |o '-' '-' o| <3v3> | * |o . o| V * |o .` `. o| * |o < > o| * |o '. .' o| * |o ' o| (PB5) error indicator * |o ___ o| (PB4) ----------------+--------+ * |o -/ _ \- o| (PB3) ------+ | | * |o -\___/- o| (PB2) --+ | .-. .-. * +---------------+ | .-. |=| |R| pulldown * | |R| |D| '-' * .-. '-' '-' | * |R| | | | * +-------------+ +---+---+ '-' .-. | V * | G6DS c | | | | | |Z| 2V1 |___ * | relay o +----+ .-. +----+ |=| Zener |___> AR9271_LED * | i | |=|f | '-' * | sw l+----+ |D|l | | ___ * +--+---+------+ | '-'y | | E--|___> 5V * | | | | b d | +--B * | |___ | | a i | C--+ * | |___> 5V +---+ c o | | * |___ | k d +---------+ * |___> AR9271_POWER | e * V */