Show Posts
Pages: [1] 2
1  Using Arduino / Project Guidance / Re: Where to put the code? on: August 28, 2011, 11:19:50 pm
Well, the linux box is also:
  my webserver
  my mailserver
  my firewall
  my timeserver
 
It's got ridiculous uptimes (not lately, cause I rebooted it a bunch of times trying to get getty to work...) but 6 or 7 months are not atypical uptimes for it.
Once it had an uptime of over 18 months. That was pretty cool. Damn power failure...

I thought about an ethernet shield, but my main question is where to put the code? I'm thinking it would be easier to maintain if the code were on the linux box than if it were in the arduino.
It won't be as cool, but when I move to a new linux box, it should be a heck of a lot easier to migrate (scp dslwatch.c dsacmul@newserver:~/dslwatch.c; ssh newserver; cc dslwatch.c -o dslwatch)...

The current linux box it's logging into is running Redhat 7.0 (gasp!)
uname --all
Linux gendep.com 2.2.18 #11 Fri Sep 20 18:39:55 MDT 2002 i686 unknown

Yep. Last kernel compile was 9 years ago. Still stable as hell...





2  Using Arduino / Project Guidance / Where to put the code? on: August 28, 2011, 10:59:15 pm
Summary: I'm building a device that will power-cycle my DSL modem when it craps out (which it does about once every three days).
Progress so far: I've etched a PCB with a 328 on it, a Max232, a relay, a 7805 and places to hang 5 LEDs. The PCB can connect via serial at 4800 bps to my ancient Linux box, and communicate reliably with the shell.

Question: Should I put the "is the internet connection okay" code in the 328, or have that code running as the login shell for the 328 when it connects?

I was thinking something like: Ping a few IP addresses (google, my Qwest-supplied DNS addresses, etc.) and if the packet loss is oh, say, greater than 80%, flop the relay.

If I put the code in the 328, then when I replace the linux box with a newer box, I'll have to reprogram the 328, but it'll be darn cool to have a little arduino login to a linux box, and reboot the DSL modem.

If I put the code on the linux box, then I can just port the source to a new box.

For the second option, I was thinking of code that runs (as a login "shell") that displays things like:
L150 L230 L350 L420 L5100 (set led 1 to 50%, 2 to 30%, 3 to 50%, 4 to 20% and 5 full on)
or
RESET
to flopify the relay

For the first option, I'll basically have to write a bunch of expect-send code for the 'duino, and although it would be cool, I think I'd rather have the code on the linux box....

Any ideas? Suggestions?


3  Using Arduino / Programming Questions / Re: Why does Arduino tend to use such low baud rates in tutorials? on: May 16, 2011, 10:32:19 pm
Oh, you young whippersnappers.
My first modem was 300 baud.
When I upgraded to 1200 baud, I was quite completely freaked out.
2400 wasn't much, but my first 9600 bps modem (a little cube that sat nicely on my NeXT Cube) was aMAZing.

9600 ain't slow.
Get off my lawn.

4  Using Arduino / Programming Questions / Re: Help with passing variables at global scope into inline assembly. on: May 16, 2011, 10:25:36 pm
Nick:
Boy, I'm sure hoping you're wrong.
I'd like a user to be able to do:
(supposing I name my class IOMonster)
IOMonster io(4,5,6,7,8)     // cmd clock, i/o clock, i/o data, cmd_data, cmd_latch

io.WriteLCD("This is a test.")
if (io.InputAvailable()) {
 .. some meaningful code...
}
io.SetLED1(50); // Set led1 at 50% duty cycle...

This is all dependent (if I'm using assembly) in having the relevant port and bit passed into my assembly routine.
At one point (when I was walking along the oregon coastline) I thought about coding a huge bunch of #ifdefs with assembly inside them to correspond to every possible port / bit combo, but decided that was a non-starter.

 If I can't pass an "I" constrained value defined at global scope into my assembly, I'll be stuck with direct I/O, which is half as fast as assembly.

Anyone know about the rules concerning passing variables at global scope into inline asm?
5  Using Arduino / Programming Questions / Re: Help with passing variables at global scope into inline assembly. on: May 16, 2011, 04:49:27 pm
Actually...
"ldi r24, %[someval]"    "\n\t"
    "pop r24"
    :
    :  [someval] "I" (var)

The "I" constraint is a qualified immediate value.
And, in my actual code (not the examples I posted here to flesh out the scope problem) the array in question is:
const uint8_t pinbits[14]={0, 1, ...};
so they're already consts, and my intention in this case is to actually pass the dang number in, but I can't if the array it's contained in is defined at global scope.


Try it yourself! It really does compile.

You can even specify (in the input operands section) an "I" constrainted value directly, like  [someval] "I" (7)
Near as I can tell, when gcc sees an "I" operand, it hardcodes in the value of the expression after the "I". What I can't understand is why scope matters.
6  Using Arduino / Programming Questions / Re: Help with passing variables at global scope into inline assembly. on: May 16, 2011, 03:07:19 pm
I actually haven't tried that. I was thinking about it, but the question of why scope even matters was really bugging me.


7  Using Arduino / Programming Questions / Re: Help needed on IR remote code on: May 16, 2011, 03:04:54 pm
I did something similar, where I had a bunch of remote codes that I got when I pushed buttons down, and then I made two arrays.
One was an array of the codes, the second was an array of pointers-to-functions that I wanted to call when those buttons were pushed.
codes are in ir_codes[], and pointers to function returning void and taking void are in funcs[]
My loop looked like:

newcode = get_ir_code();
for (int i=0; i<maxcode; i++) {
  if (newcode==ir_codes) {
    (*funcs)();
    break;
  }
}
At the top (at global scope -- see my other thread for global scope woes) was:
#define maxcodes 10
unsigned long int ir_codes[maxcodes] = { 0x4421305f, 0x4421303f, ... };
void (*funcs[maxcodes])(void) = {&OneKeyPushed, &TwoKeyPushed, ...};

Since the high 16bits of each IR value was the same, and being a memory miser, I eventually, just stored the low 16 bits in an int, and
cut down on ram by a little bit.

Holler if you want the code.
(I can get the files off my server at home -- on vacation atm).

8  Using Arduino / Programming Questions / Thanks for the wiring suggestions... but what's up with the scope problem? on: May 16, 2011, 02:50:28 pm
Why does:
int b=4
void poo(void)
{
 asm volatile (
  "LDI r24, %[value]"
  :
  : [value] "I" (b)
  :
  );
}
not compile if b is at global scope, but does compile if b is in local scope?
I'm doing a bit more with my shift registers than I explained in the original post, and, when I'm done, I want a little board that'll handle a whole buncha stuff for $1.80 in parts. Plus, I'd like to be able to abstract the whole thing and encapsulate it in a class so that it'll be super spiffy. Right now, having to hardcode the ports is a definite downer.

I appreciate the wiring suggestions, but mostly I'm concerned with the scope issue.

9  Using Arduino / Programming Questions / Re: Digital toggle question - very basic question on: May 15, 2011, 10:26:51 pm
Unless I'm very much mistaken, the presence of the Serial.print() and Serial.println() methods inside your loop are the likely culprit. Serial.print() blocks until output is complete, and that can be many many milliseconds.
Try taking the Serial calls out, and see how it performs (or crank up the baud rate considerably in the serial.setup() call...)

Maybe put a switch on a new pin (say... 11?) with a pulldown and if it's high, do a serial output...

if (digitalRead(4)==HIGH) {
Serial.print("Current counter is bleh bleh bleh");
Serial.println(variable);
Serial.println("Counting suspended untill switch is opened...");
delay(50); // To help debouce the switch...
while (digitalRead(4)==HIGH);  // Empty loop.
}

+5 to one side of the switch, other side of the switch a 10k resistor going to ground, and a wire going to the junction of the resistor and the switch leg from arduino pin 4... Happy pulldown.

Perhaps that'll help.



Then you press your button, and as long as it's held down the program will sit there waiting for you to let it go, and then resume counting happily.

10  Using Arduino / Programming Questions / Re: Help with passing variables at global scope into inline assembly. on: May 15, 2011, 09:48:46 pm
I'm building a box that has 8 total wires headed into it, and I want to be able to:
1. Read a rotary encoder
2. Drive an LCD display
3. Read a 3-position switch
4. Read 3 SPST switches
5. (Optional) drive a high-intensity LED with PWM

I can scrap the LED if need be.

I've got a 597 and a 595 working together nicely, with the 595 talking to a cheapo LCD in 4-bit mode, (d7-d4 inclusive to A-D outputs on the 595), RS (The command bit) coming from E on the 595, and the ENA pin on the LCD taking up an arduino pin.
Then I stuck the 597's latch, load, and clock pins on the other three outputs of the 595.

So, to spit a byte to the LCD, I did:
ENA low
put RS followed by HIGH nibble into the 595
Latch
Put RS (again) and low nibble into 595
Latch again

To mess about with the 597, I'd just scoot the bits over.
Problem came when I wanted to pack it all into an ISR, (Eventually, I'd like a CheapLCD.Print(const char *) method that will feed 8 or so bytes at a time into a circular buffer, and return when the buffer is empty. The same ISR that reads byte off the queue will also (every 2ms or so) poll the 597. I should be able to debounce pretty quickly in the ISR.)
Problem was, writing this thing all nibbly like that, I had no control, really, over what the F G and H bits out of the 595 going to the 597 were without using yet another arduino pin to toggle the Master Reclear pin on the 595. So, I figure, why not talk to the LCD in 8 bit mode, and devote an entire 595 to it, it can share a clock with the 597, and if I latch both of them through another 595, I can do input or output through a 595.
I did direct port manipulation, and got 3097 characters in 251 msec.
With assembly, I got 3097 characters in 128 msec.
With digitalWrite, I got 3097 characters in 1530 msec.
My routines are a bit more convoluted than the example I posted to open this thread up. Mostly, I was (and continue to be) puzzled by why I can't pass a value into inline assembly that's declared at global scope.
For example:
Code:
void setup(void)
{
  // meh;
}

void loop(void)
{
  // double meh
  asm_blob();
  delay(1200);

}
int bar[3]={ 1, 2, 7  };
void asm_blob(void)
{

  uint8_t var = bar[2];

  asm volatile (
    "push r24"                "\n\t"
    "ldi r24, %[someval]"    "\n\t"
    "pop r24"
    :
    :
    [someval] "I" (var)
    :
  );

}
This doesn't compile.

Move the declaration of bar into function asm_blob, however...
Code:
void setup(void)
{
  // meh;
}

void loop(void)
{
  // double meh
  asm_blob();
  delay(1200);

}
void asm_blob(void)
{
  int bar[3]={ 1, 2, 7  };

  uint8_t var = bar[2];

  asm volatile (
    "push r24"                "\n\t"
    "ldi r24, %[someval]"    "\n\t"
    "pop r24"
    :
    :  [someval] "I" (var)
    :
  );
}


 That works fine.

Global scope. Why u no compile?
 
11  Using Arduino / Programming Questions / Help with passing variables at global scope into inline assembly. on: May 15, 2011, 01:33:16 pm
I'm trying to control a parallel LCD with a 595 shift register, and control >that< 595 with another 595, and using some of my leftover outputs on the second 595 to control a 597 (I'm low on pins...).

So, dissatisfied with code like:
Code:
void shiftout(void)
{
  uint8_t mask=1;
  for (int i=0; i<8; i++) {
    if ((outbyte & mask)==0)
      digitalWrite(dpin, LOW);
    else
      digitalWrite(dpin, HIGH);
    HL(dclk);  // Toggle clockpin.
  }
  HL(dlat);    // Toggle latchpin
}
because of the massive overhead that comes along with digitalWrite, I decided to try in assembly.
(Oh, this code worked just fine, but was only able to output about 2 characters per millisecond, or 20kbps. Waaay to slow for an isr...)

I wrote:
Code:
void shiftout_asm(void)
{
  asm volatile (
    "SBI %[datport], %[datbit]"    "\n\t"  // digital write HIGH
    "SBRS %[outb], 0"              "\n\t"  // is bit 0 set?
    "CBI %[datport], %[datbit]"    "\n\t"  // No. dW low...
    "SBI %[clkport], %[clockbit]"  "\n\t"  // Clock high
    "CBI %[clkport], %[clockbit]"  "\n\t"  // and low..
    "SBI %[datport], %[datbit]"    "\n\t"  // digital write HIGH
    "SBRS %[outb], 1"              "\n\t"  // is bit 1 set?
    "CBI %[datport], %[datbit]"    "\n\t"  // No. dW low...
    "SBI %[clkport], %[clockbit]"  "\n\t"  // Clock high
    "CBI %[clkport], %[clockbit]"  "\n\t"  // and low..
    // ... rinse and repeat for bits 2-6 code ommitted for brevity
    "SBI %[datport], %[datbit]"    "\n\t"  // digital write HIGH
    "SBRS %[outb], 7"              "\n\t"  // is bit 7 set?
    "CBI %[datport], %[datbit]"    "\n\t"  // No. dW low...
    "SBI %[clkport], %[clockbit]"  "\n\t"  // Clock high
    "CBI %[clkport], %[clockbit]"  "\n\t"  // and low..
    "SBI %[latport], %[latpin]"    "\n\t"  // latch high
    "SBI %[latport], %[latpin]"    "\n\t"  // And low, and we're
                                           // shifted and happy.
    : // no output operands
    : [datport] "I" (_SFR_IO_ADDR(PORTD)), [datbit] "I" (6), //PIN6
      [clkport] "I" (_SFR_IO_ADDR(PORTD)), [clkbit] "I" (3), //PIN3
      [latport] "I" (_SFR_IO_ADDR(PORTD)), [clkbit] "I" (7), //PIN7
      [outb] "r" (outbyte)
    : // No clobbers
  );
}
And, after several hours of compiler-fighting, got it to work. Much more impressive, with upwards of 25kCPS, 250kbps...
If I stick this:
volatile uint8_t *data_port=&PORTD;
and the corresponding SFR in the input operands section to:
_SFR_IO_ADDR(*data_port)
It compiles and works fine.
However, if I move the definition of uint8_t data_port to global scope, it won't compile.
I get an "impossible constraint in ASM" error with the input operand that is defined at global scope.
I've not investigated this a great deal, but I can't even pass one of the immediate values (the pin numbers) if they're in variables declared at global scope.

This forum request for help may be a bit premature, but I'm on vacation, and this is driving me batty, trying to figure this out with awful wireless in hotels in Oregon.

Anyone been through this have an "Oh! Here's what you need to do" to throw at me?

Thanks.



12  Development / Suggestions for the Arduino Project / Re: Out-of-memory check on: April 03, 2011, 10:44:47 pm
This is kind of reminiscent of some Corewars programs I wrote a long time ago...
13  Development / Suggestions for the Arduino Project / Re: Shift-Ctrl M (to open Serial Monitor) inserts a carriage return in the editor. on: April 03, 2011, 01:13:14 pm
I've never done much coding (well, really any coding) in Java, but I poked around in the source a bit, and it looks like an
event.consume()
would eat the keystroke before it got sent to the editor.

Just don't know where to put it.

Hmm.
14  Development / Suggestions for the Arduino Project / Re: Basic suggestions for IDE usability improvements on: April 03, 2011, 11:47:29 am
I heartily second the "active serial port" and "active board type" notifiers.

There's lots of real estate in the ide -- That big blue bar on the bottom that houses the incredibly tiny line number, for instance (it's capable of being updated dynamically as the cursor moves around, stick "Serial: /dev/ttyACM0" on the right side of the bar. That'd be sweet when you've got two instances of the IDE open, and you're wondering... "Is board one on /dev/ttyUSB0 or /dev/ttyUSB1?"

I usually unplug a USB then do a quick "ls /dev/ttyU*" to see which one I unplugged...

15  Development / Suggestions for the Arduino Project / Shift-Ctrl M (to open Serial Monitor) inserts a carriage return in the editor. on: April 03, 2011, 11:40:28 am
I'm a keyboard shortcut kinda guy (my second word processor was WordStar, and I still have to tell my brain not to hit ^K^P to open the print menu, no, it's just ^P now...)

Sometimes I forget to move the cursor to a blank place in my code when I want to pop up the monitor, and end up with stuff like:

if (i =
=6) {   (If the cursor was between the equal signs when I hit SHIFT-CTRL M)

Which, of course generates an error. It can be a bit tedious. Also, when I do remember to move the cursor somewhere reasonable before hitting the shortcut, I end up with code that looks like a high school student tried to pad out a 20 page paper (lots of vertical whitespace) and have to go back and re-edit the file. The IDE does strange things when the mouse pointer is over the tools menu (like reset the boards) in Ubuntu, and this shortcut is a bit of a longcut.



Could the IDE be modified so that if SHIFT-CTRL M is pressed to just open the monitor and not insert a CTRL-M (CR)?
Pages: [1] 2