Loading...
  Show Posts
Pages: 1 2 3 [4] 5 6 ... 75
46  Using Arduino / Programming Questions / digitalWrite writes a byte, while digitalRead returns an int. Why? on: February 14, 2013, 07:21:38 pm
Code:
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;

if (port == NOT_A_PIN) return;

// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);

out = portOutputRegister(port);

uint8_t oldSREG = SREG;
cli();

if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}

SREG = oldSREG;
}

int digitalRead(uint8_t pin)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);

if (port == NOT_A_PIN) return LOW;

// If the pin that support PWM output, we need to turn it off
// before getting a digital reading.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);

if (*portInputRegister(port) & bit) return HIGH;
return LOW;
}

I was looking at the code of these functions to see what type I should use for a wrapper function when passing HIGH and LOW, and I noticed they used different types.  Since a byte obviously works to hold the value, and takes up less memory, and produces faster code, why does digitalRead return an int?
47  Using Arduino / Microcontrollers / Need help with compiling SD card booloader on: January 13, 2013, 02:39:22 am
Hey guys,

I found this bootloader a while back which allows you to load programs off an SD card:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=72303

I have modified the code to use USART0 instead of SPI, and to flash the bootloader if the version number doesn't match the current version, rather than only if it is greater, and now I need to compile it.

I was hoping that I could do this from within the Arduino IDE, but it doesn't seem like that is possible.  Do I need to install AvrStudio to do this?  Or can I just use a make file of some kind?  I don't know anything about using makefiles.  And the tutorial is confusing, referencing a lot of stuff without explanation of what it is or where it is found.  For example:

Quote
The programmer must put the bootloader into the bootloader section. This is quite easy and just requires reassinging .text (default 0x0000) to the bootloader start address.

I have no idea what ".text" is.  Is it a file?  It is a variable somewhere?  Is it something from a make file?  Is it a setting in AvrStudio?  No clue.

Quote
Lastly, in Project-->Configuration Options-->Memory Settings, click Add, and configure
Code:

Memory type: flash
Name: .text
Address(Hex): 0x3800

This can be done with a the linker command -tText, too, although I forget the exact syntax.

Part of my confusion is that it says "lastly" there as if this is another step in addition to setting .text somewhere.  But perhaps it is just something set in AvrStudio.  But it seems to be something I might simply be able to do from the command line when burning the bootloader? 

Why is this variable called .text anyway?  If it's the bootloader start addres why isn't it .address or something?

Also, in regards to the bootloader code itself, how does it find the program on the SD card?  I don't see any mention of a specific filename.  The code seems to be engineered to look for files, and scan every single one it comes across for a particular size and version number and then additional information.  Is that right?  I guess if it skips files that aren't a specific size it won't be too slow scanning with lots of other files on there, but it seems like it could potentially mistake a wav file for the program.  I guess the chances of that are incredibly slim, but I'd kinda feel better if it looked for a bin extension.
48  Using Arduino / Motors, Mechanics, and Power / Re: I'm getting a lot of static when driving servos. on: January 13, 2013, 12:36:58 am
Just a quick update to mention that I found one of those clip-on ferrite things on a spare cable I had and stuck it on the servo wire to see if that would have any affect on the noise, but it didn't make any difference.   
49  Using Arduino / Motors, Mechanics, and Power / Re: I'm getting a lot of static when driving servos. on: January 09, 2013, 02:15:04 pm
Well, I just did a couple tests with some interesting results.

First, I discovered that my cheap chinese switching regulators which are supposed to supply up to 3A seem to fail when I use them as my power source and try to drive a servo.  Mostly I've been running off USB power when doing my tests, and I know that can only supply up to 500mA.  So something weird is going on.  I know the switching regulators can actually supply up to 5A peak because I tested them with my multimeter. 

So perhaps the issue is the switching regulator is unable to supply power quickly.  There's some 220 ohm caps on the input and output of the regulator though, so I'm not sure what more could be done there.  The regulator on these boards is the LM2596S: http://www.ti.com/product/lm2596

Or, maybe the problem is the power source itself, which is six C cells of unknown age.  I don't have any LiPoly batteries to test with though.  I suppose I could try fresh C cells.

Anyway, the other test I did was to run the main board on USB power, power the servo with the voltage regulator, and connect the grounds.  This worked like a charm.  The huge amounts of static I was getting disappeared.  So I know the static isn't coming from the servo's signal line, or from emf getting into my audio lines.  It must be from the power.  Perhaps an inductor or some caps would help there, but until I know the voltage regulator can even power the servo at the same time as the board with an adequate power source, I'm not gonna mess around with that.

At least I know now I can drive servos without noise if I use a separate power source.  That at least is a workable solution.   

Oh, and I did finally test the vibration motor going with a quiet sound effect going and I do notice that I can hear some quiet pops with that.  So even the vibration motor isn't immune from causing noise.  I guess I should have used an inductor on that, but it's not really a major concern since the only time you really use the vibration normally is with loud sound effects.


50  Using Arduino / Motors, Mechanics, and Power / Re: I'm getting a lot of static when driving servos. on: January 09, 2013, 03:33:35 am
I just remembered something. 

My boards don't have an onboard voltage regulator.  I use an external regulator or USB power to supply the 5V I need.  Or I power it directly from 3 AA batteries.  This means I couldn't add a linear regulator for my audio, because to supply 5V to the audio circuit I'd need to supply the regulator with more than 5V.

I suppose I could create a servo control module of some kind which uses an external power source, but the whole point of this board is to be as small as possible and be a light, sound, and motion controller.  A separate servo module would likely not fit in a small handheld prop with servos.

Any other ideas for how I could prevent noise from getting into my audio circuit?  Inductors where the digital power and ground planes connect to the analog ones perhaps?  I've seen inductors in some papers I've looked at.  But my budget and space constraints didn't really allow for them at the time and I thought I could get away without them.  Is it possible to get really tiny inductors? 

Oh, and the reason I used an external regulator was because late in my design process I discovered the linear regulator I was going to use wasn't going to be able to supply more than 2A without melting my board down and I didn't have space for a heat sink, or the money, space, or time to add a switching regulator, so I ended up purchasing a bunch of fixed 5V switching regulators to get the job done.


 

51  Using Arduino / Microcontrollers / Re: Does the latest IDE support 644P and 1284P? on: January 07, 2013, 02:58:01 pm
While we're on the subject of supporting other processors, you know what would be really awesome would be XMEGA support.  I'm not sure why they chose to go with the arm processor they used in the DUO, but that chip is huge and seems to require a whole lot of support circuity.  I don't think I'd ever want to take that processor and stick a bare bones version in my own project.  The xmega on the other hand comes in a small 44 pin version, looks easy to use, has a built in DAC for audio output...  Aside from running a 3.3v potentially being a problem for controlling servos, for projects that need a little bit extra oomph, and 32mhz xmega seems like an excellent choice for an upgrade if you need twice the speed and/or audio output.
52  Using Arduino / Motors, Mechanics, and Power / Re: I'm getting a lot of static when driving servos. on: January 07, 2013, 02:47:07 pm
You are generating audio only?

What do you mean? 

I am reading audio from an SD card, updating LEDs, reading inputs, and turning pins on and off for a strobe and vibration motor, but none of that generates any noise in the line.  I only get noise when I have a servo plugged in and I'm actively moving it.

Quote
In that case the chief suspect is the supply rail - you should power audio DAC + amps from a separate power
rail with its own regulator and at lots of decoupling (0.1iF + 10uF + 100uF for instance).  Separate voltage regulator is _vital_ if your
DAC's reference voltage is the supply rail (and it needs to be linear, not switch-mode).

Hm, well it's far too late for that, but I'll keep it in mind in the future.  What about the ground though?  Even if I have it on a separate 5v rail, the grounds must still be shared.

Quote
The layout looks good and you don't appear to have low-level audio signals that could be picking up RFI.

I'm not sure what you mean by this either.
53  Using Arduino / Programming Questions / Re: Can someone help me figure out what this loop is doing? on: January 07, 2013, 02:18:25 pm
Well I was thinking more along the lines of the data line just being stuck high while the card isn't responding.
54  Using Arduino / Motors, Mechanics, and Power / I'm getting a lot of static when driving servos. on: January 07, 2013, 01:53:18 pm
My board is designed to output audio and control servos, and I've just found that when driving a medium sized servo I get a lot of static on my audio output every time it changes direction, and some static when it's just turning as well.  Even with a tiny servo, I can hear static if I'm preventing it from turning.

I thought the servos would have a reverse protection diode built in as well as some capacitors to reduce noise since noise on the data lines could potentially result in crashed airplanes, but if they're in there, they don't seem to be doing a very good job. 

I also don't seem to have done a very good job at isolating my audio from this sort of noise in my circuit.  I did make sure to have only one entry and exit point for the current into the audio portion of the circuit, and it's on the other side of the board from the servo ports, and the power source is between the two, so I thought that would be sufficient to avoid this issue, but apparently my efforts were either insufficient, or the noise is being radiated from the servo line and the audio line is picking it up or something.  But I suspect it's direct transfer on the board itself.

You can see the layout of my board here.  The servo is attached to port 9.  So the current for the servo either flows in from the top of the board from the mosfet on the top right, or under the microcontroller and past the switch, I'm not sure.  The audio portion is in the lower right, and there is a fairly straight line for the positive plane to the mosfet, but the ground plane current has to go around the LED pins: 
http://shawnswift.com/arduino/mighty-layout.png   

This was as good as I could get it, and as far as noise from other sources goes, like a vibration motor I've got attached via a mosfet and with a protection diode...  That works just fine.  I don't hear any noise at all from it.  And I'm switching it on and off rapidly.  It's just these darn servos, which are plugged into the same ports that are the issue.

Is it perhaps just the servos are inadequately noise protected?  I mean I hardly did anything for my vibration motor other than that diode.  Might there be some way to modify a servo cable to reduce the noise?  Put a choke on it for example?   
55  Using Arduino / Programming Questions / Re: Can someone help me figure out what this loop is doing? on: January 07, 2013, 01:31:56 pm
If the card did return 0, then you would get:

0x00 & 0x80 = 0 = false, which means the loop would be broken.

That's why I'm asking.  I would expect the card to return 0 if it's not responding.  But maybe it returns 0xFF instead, until it responds, and then it responds with that particular bit not being set. 

Anyway I guess this code was not what was broken because I found the issue elsewhere. 
56  Using Arduino / Microcontrollers / Re: Does the latest IDE support 644P and 1284P? on: January 07, 2013, 01:28:22 pm
Just an observance that I upgraded to the arduino IDE version 1.0.3 and was getting errors when a 1284p board was selected and trying to verify a sketch, but not when a Uno board selected. One error was INPUT_PULLUP not defined and I think byte not a type, etc. What I did was copy the Arduino.h file from 1.0.3 and replaced the one used in the added hardware files and that seemed to work. I guess my main question would be are there other changes required? Seems that adding new/different boards types to the users hardware files will never be completely independent of the version of IDE being used, so on going maintenance is probably a never ending requirement?

Lefty


Yes I ran into this problem myself.  Apparently definitions for certain constants like INPUT_PULLUP are in those hardware specific folders.  Seems like a bad design decision to me.  I can't see a reason to make a constant like that hardware specific.
57  Using Arduino / Networking, Protocols, and Devices / Re: Having trouble interfacing with SD card. One works, another doesn't? on: January 06, 2013, 09:37:44 pm
I've found the problem!

The answer came when I noticed this bit in the datasheet un the USART MSPI section:

Quote
Note: To keep the input buffer in sync with the number of data bytes transmitted, the UDRn register must
be read once for each byte transmitted.

I was not doing that.  I was never doing that.  Originally, unable to get buffered reads working, I'd resorted to a hack, treating the USART as unbuffered and making sure each transmit completed before exiting the send function.  I believe a side effect of this was bytes were being lost when reading them, because the read function first called the send function, and I think there may have been some bug resulting from that. 

The weird thing is that my generic brand SD card tolerated these errors somehow, and my code worked with it.  But it would not work with SanDisk cards.

Anyway, it works perfectly now.  You can see the diagnostic here of the brand name card which was not working previously:

Code:
init time: 388

Card type: SD2

Manufacturer ID: 3
OEM ID: SD
Product: SU01G
Version: 8.0
Serial number: 1366936321
Manufacturing date: 10/2007

card size: 1984000 (512 byte blocks)
partion,boot,type,start,length
1,0,6,249,1983751
2,0,0,0,0
3,0,0,0,0
4,0,0,0,0
Read test starting. Please Wait.

Read 20000 blocks
mills: 19371

Done


And here is the diagnostic of the generic card.  The read speeds have been increased significantly from what they were.  Perhaps this is indicative of how many bytes were being read multiple times or lost as a result of the buggy hack version of the send function:

Code:
init time: 20

Card type: SD2

Manufacturer ID: 0
OEM ID:   
Product: N/A 
Version: 1.0
Serial number: 3664195770
Manufacturing date: 7/2012

card size: 1968128 (512 byte blocks)
partion,boot,type,start,length
1,0,6,253,1967875
2,0,0,0,0
3,0,0,0,0
4,0,0,0,0
Read test starting. Please Wait.

Read 20000 blocks
mills: 22234


And finally, here is the code.  I've included the original SPI functions, and the USART ones I wrote that now work properly with buffering:

Code:
inline void spiSend(uint8_t b) {SPDR = b; while(!(SPSR & (1 << SPIF)));} // Original SPI code.
inline void spiSend(uint8_t b) {while(!(UCSR0A & (1 << UDRE0))); UDR0 = b; b = UDR0; } // New buffered USART code.

inline uint8_t spiRec(void) {spiSend(0XFF); return SPDR;} // Original SPI code.
inline uint8_t spiRec(void) {while(!(UCSR0A & (1 << UDRE0))); UDR0 = 0xFF; while(!(UCSR0A & (1 << RXC0))); return UDR0;} // New buffered USART code

You'll note I haven't used the spiSend() function in the spiRec() function for the USART, as is done with the SPI code.  That's because the send function reads a byte at the end, and that would be lost if I didn't read it.

It may be there is still a bug in here, or that it can be optimized further. 

For example, if you look at spiRec() you'll note I wait for a receive flag to be set before I return the byte.  But I don't do that in the send function.  It may be that I need to do that in the send function as well before I try to read a byte from the buffer.  I'm not sure.  The datasheet does not seem to indicate I need to.  But if I send a byte, and it's placed in the buffer, and then I immediately read one, where will that read byte come from?  It can't be in the buffer if the sent byte hasn't actually transmitted yet because I only get a byte back as I am transmitting one.  So I'm not sure that this data transmission is entirely in sync yet. 

Also, rather than just setting b = UDR0, I could return UDR0 from the send function.  Then I could just define spiRec() to be spiSend(0xFF) and be done with it.  But before I do that I want to be sure about whether I need to check that receive flag.

Still looking at the documentation to try to figure out what I should do.  Page 202 here:
http://www.atmel.com/Images/doc8059.pdf

And page 5 here:
http://www.atmel.com/Images/doc2577.pdf
58  Using Arduino / Networking, Protocols, and Devices / Having trouble interfacing with SD card. One works, another doesn't? on: January 06, 2013, 01:28:07 pm
Hey guys,

I recently discovered that while my code works fine with the generic SD card I've been testing with, my Sandisk cards don't work at all. 

I suspect there may be a bug in my code, but so far I've failed to track it down.

I've already checked the obvious potential problems.  The cards are not high capacity cards.  They're formatted the same using the same official SD card formatting utility.  And all the files copied to them are intact.

I have also tried disabling partial block reads, and slowing down the SPI bus.  Oh, and I'm not using voltage dividers to talk to the cards, they're connected with an actual buffer and running a 3.3v. 

It may be worth noting that I am using the USART in MSPI mode to talk to the SD card.  This works fine with the generic card, and I've been happily playing wav files off the card for weeks.  But one thing that has been bugging me is that I cannot seem to write to the car using buffered output.  That fails every time.  Checking each time to make sure the byte is transmitted before I continue works fine though.

Here is the transmit code I'm using:

Code:
void printbyte(uint8_t b) {
char t[4]; // 3 chars + null
sprintf(t, "%u", b);
Serial1.println(t);
}

//------------------------------------------------------------------------------
// inline SPI functions

/** Send a byte to the card */

//inline void spiSend(uint8_t b) {SPDR = b; while(!(SPSR & (1 << SPIF)));} // Original code.

// while(!(SPSR & (1 << SPIF))); loops until the SPIF bit is set.  Or rather, loops while it is clear.
     // Alternatively, avr/io.h could be included, and the following done: SPDR=(dat); loop_until_bit_is_set(SPSR,SPIF)

// Transmit byte via USART0 configured in MSPI mode:

inline void spiSend(uint8_t b) {UCSR0A = (1 << TXC0); UDR0 = b; while(!(UCSR0A & (1 << TXC0))); Serial1.print("SEND: "); printbyte(b);} // Last working version
//inline void spiSend(uint8_t b) {while(!(UCSR0A & (1 << UDRE0))); UDR0 = b;} // This seems to be the standard method.  Does not wait for byte to finish transmitting to exit.


/** Receive a byte from the card */

// Receive a byte using SPI:
//inline uint8_t spiRec(void) {spiSend(0XFF); return SPDR;} // Original code.

// Is it actually necessary to send 0xFF? Or is it important we just transmit SOMETHING?

// Recieve byte via USART0 configured in MSPI mode:
inline uint8_t spiRec(void) {spiSend(0XFF); while(!(UCSR0A & (1 << RXC0))); Serial1.print("RECV: "); printbyte(UDR0); return UDR0;} // Master must transmit a byte to receive one.



I don't usually have the code in there to print the debug data, so that's not the issue.


Here are the results I get testing with three different cards:

Code:
BEGIN - Goodcard

type any character to start

init time: 913

Card type: SD2

Manufacturer ID: 0
OEM ID:   
Product: N/A 
Version: 1.0
Serial number: 3664195770
Manufacturing date: 7/2012

card size: 1968128 (512 byte blocks)
partion,boot,type,start,length
1,0,6,253,1967875
2,0,0,0,0
3,0,0,0,0
4,0,0,0,0
Read test starting. Please Wait.

Read 20000 blocks
mills: 36949

Done

type any character to start





BADCARD1:

type any character to start

init time: 468

Card type: SD2

Manufacturer ID: 3
OEM ID: SD
Product: SU02G
Version: 8.0
Serial number: 2897907216
Manufacturing date: 9/2008

cardSize failedSD error
errorCode: 8
errorData: 0



BADCARD2:

type any character to start

init time: 390

Card type: SD2

Manufacturer ID: 3
OEM ID: SD
Product: SU01G
Version: 8.0
Serial number: 1366936321
Manufacturing date: 10/2007

cardSize failedSD error
errorCode: 8
errorData: 0


This was before I put the code in to print out the individual bytes sent.  After I did that, this is what I get with one of the non working cards:

Code:
SEND: 255
SEND: 255
SEND: 255
SEND: 255
SEND: 255
SEND: 255
SEND: 255
SEND: 255
SEND: 255
SEND: 255
SEND: 255
RECV: 0
SEND: 255
RECV: 127
SEND: 255
RECV: 255

... (hundreds of 255's sent and received here) 

SEND: 64
SEND: 0
SEND: 0
SEND: 0
SEND: 0
SEND: 149
SEND: 255
RECV: 255
SEND: 255
RECV: 255
SEND: 255
RECV: 255
SEND: 255
RECV: 255
SEND: 72
SEND: 0
SEND: 0
SEND: 1
SEND: 170
SEND: 135
SEND: 255
RECV: 255
SEND: 255
RECV: 255
SEND: 255
RECV: 0
SEND: 255
RECV: 0
SEND: 255
RECV: 1
SEND: 255
RECV: 170

card.init failed
SD error
errorCode: 9
errorData: 1

The two error codes I've gotten are the following:

Code:
/** read CID or CSD failed */
#define SD_CARD_ERROR_READ_REG 0X8

/** bad response echo from CMD8 */
#define SD_CARD_ERROR_CMD8_ECHO 0X09

I'm guessing the difference between the error I got before the debug and after it is there's a millisecond timer somewhere timing out because of the debug data I'm sending. 

Also, I should note that when running my main program rather than this test app, the cards seem to initialize fine, and the FAT code successfully opens the root directory.  But loading and playing the wave files fails.

I really think the error might be with how I'm trying to use the USART in MSPI mode because those buffered writes should work, but they don't.  If someone could confirm whether that bit of code is right or not then that would be a start at least.  It seems to be the same as the examples I've seen.

Here's the full source of the modified WaveHC lib I'm using to interface with the card.  It includes in the examples folder the test program which generated the above outputs:
http://shawnswift.com/arduino/WaveHC.zip

The code in question is in the sdreader.cpp file.  The wave playback code isn't broken or used in the test.
59  Using Arduino / Programming Questions / Can someone help me figure out what this loop is doing? on: January 06, 2013, 12:39:46 pm
Code:
  // send CRC
  uint8_t crc = 0XFF;
  if (cmd == CMD0) crc = 0X95; // correct crc for CMD0 with arg 0
  if (cmd == CMD8) crc = 0X87; // correct crc for CMD8 with arg 0X1AA
  spiSend(crc);
 
  // wait for response
  for (uint8_t retry = 0; ((r1 = spiRec()) & 0X80) && retry != 0XFF; retry++);

The bit there where it waits for a response is confusing me. 

If I understand this correctly, a byte is read from the SD card into R1.  R1 is then ANDed with 0x80.  So it appears to be looking to see if a particular bit is set in the reply.  If no bit is set, then that side of the equation evaluates to false.

Then retry is compared to 0xFF.  If it isn't 0xFF, then it evaluates to true, and the loop continues.  This makes sense.  It's trying 255 times to get the response its looking for.

But it's the first part that doesn't make sense to me.  If it's waiting for a response from the card, why does it continue only if a particular bit is not set?  Wouldn't a card that is not responding return 0?  And wouldn't 0 & 0x80 evaluate to false, and cause the loop to exit prematurely?

60  Using Arduino / Networking, Protocols, and Devices / Poblem with USART in MSPI mode on: January 05, 2013, 01:48:54 pm
Hey guys,

I've got a board with a MicroSD card on USART0, and while I've managed to convert some code that used to use the SPI to talk to the SD card to use the USART, in order to make that happen I had to kludge things a little.

Here's the code:

Code:
/** Send a byte to the card */

//inline void spiSend(uint8_t b) {SPDR = b; while(!(SPSR & (1 << SPIF)));} // Original code.


// Transmit byte via USART0 configured in MSPI mode:

//inline void spiSend(uint8_t b) {UCSR0A = (1 << TXC0); UDR0 = b; while(!(UCSR0A & (1 << TXC0)));} // Last working version
inline void spiSend(uint8_t b) {while(!(UCSR0A & (1 << UDRE0))); UDR0 = b;} // This seems to be the standard method.  Does not wait for byte to finish transmitting to exit.


/** Receive a byte from the card */

// Receive a byte using SPI:
//inline uint8_t spiRec(void) {spiSend(0XFF); return SPDR;} // Original code.

// Recieve byte via USART0 configured in MSPI mode:
inline uint8_t spiRec(void) {spiSend(0XFF); while(!(UCSR0A & (1 << RXC0))); return UDR0;} // Master must transmit a byte to receive one.

The problem I'm having is with the send function.  If I use the "standard method" which checks to see if the buffer is ready for another byte to be stuffed into it, my code doesn't work.  The SD card doesn't initialize.  If however I use the kludge method, where I clear the transmit complete bit, then send the data, then wait for the transmission to finish, which is more similar to what happens in an SPI transfer, then the code works just fine.

But I can't figure out why.  If I transmit a byte, using the standard function, then transmit a few more, it should wait when needed.  And if I attempt to read a byte after transmitting one, again, the code should wait till it's okay to send, and then wait until it gets a byte back.

So it should work.  But it doesn't.

Any ideas?
Pages: 1 2 3 [4] 5 6 ... 75