Show Posts
|
|
Pages: [1] 2
|
|
1
|
Products / Arduino Due / Re: I2C + DMA
|
on: May 02, 2013, 07:10:42 am
|
|
Added corrections to the code above, now setting the STOP flag prior to transferring data. This code works correct only for 1-byte transfers, see top of post.
|
|
|
|
|
2
|
Products / Arduino Due / Re: I2C + DMA
|
on: May 01, 2013, 02:11:00 pm
|
EDIT2: Warning: this code does not correctly set the stop condition. It should be set prior to the last byte being transferred. For an N-byte transfer, we can transfer N-1 bytes by PDC, then interrupt, set the STOP flag and then send the last byte, also by PDC. I've edited this code to always set the stop condition before activating the PDC, which works for 1-byte transfers. You can put it together or I might post my library when it's finished  /EDIT I've got I2C working with PDC. It wasn't easy and the code is not pretty (yet) but it should get you started! I'm writing an event-driven architecture where multiple drivers can communicate with one device each on the same I2C bus. There's some work left but when I'm done I should be able to run multiple I2C devices with nearly zero CPU overhead  #include <Arduino.h> #define DeviceID 0x34 #define DeviceAddress 0x68 #define MPU6050_RA_WHO_AM_I 0x75 #define MPU6050_WHO_AM_I_BIT 6 #define MPU6050_WHO_AM_I_LENGTH 6 #define TWI_CLOCK 100000 uint8_t count = 0; bool didWeRead; enum ServiceState : uint8_t { FinishedReading, FinishedWriting, FinishedWaiting, };
static inline void TWI_PDCWrite(uint8_t *data, uint16_t count) { WIRE_INTERFACE->TWI_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS; WIRE_INTERFACE->TWI_TPR = (RwReg)data; WIRE_INTERFACE->TWI_TCR = count; WIRE_INTERFACE->TWI_TNPR = 0; WIRE_INTERFACE->TWI_TNCR = 0; } static inline void TWI_PDCRead(uint8_t *data, uint16_t count) { WIRE_INTERFACE->TWI_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS; WIRE_INTERFACE->TWI_RPR = (RwReg)data; WIRE_INTERFACE->TWI_RCR = count; WIRE_INTERFACE->TWI_RNPR = 0; WIRE_INTERFACE->TWI_RNCR = 0; }
static inline void TWI_MasterModeWrite(uint8_t deviceAddress) { WIRE_INTERFACE->TWI_MMR = TWI_MMR_IADRSZ_NONE | TWI_MMR_DADR(deviceAddress); WIRE_INTERFACE->TWI_CR = TWI_CR_MSEN; } static inline void TWI_MasterModeRead(uint8_t deviceAddress) { WIRE_INTERFACE->TWI_MMR = TWI_MMR_IADRSZ_NONE | TWI_MMR_DADR(deviceAddress) | TWI_MMR_MREAD; WIRE_INTERFACE->TWI_CR = TWI_CR_MSEN; }
static inline void TWI_Write() { didWeRead = false; WIRE_INTERFACE->TWI_CR = TWI_CR_START | TWI_CR_STOP; WIRE_INTERFACE->TWI_IER = TWI_IER_ENDTX; WIRE_INTERFACE->TWI_PTCR = TWI_PTCR_TXTEN; } static inline void TWI_Read() { didWeRead = true; WIRE_INTERFACE->TWI_CR = TWI_CR_START | TWI_CR_STOP; WIRE_INTERFACE->TWI_IER = TWI_IER_ENDRX; WIRE_INTERFACE->TWI_PTCR = TWI_PTCR_RXTEN; }
void write() { TWI_PDCWrite(&count, 1); TWI_MasterModeWrite(DeviceAddress); TWI_Write(); count++; } uint8_t received[8]; void read() { TWI_PDCRead(received, 8); TWI_MasterModeRead(DeviceAddress); TWI_Read(); } void InitializeTWI() { pmc_enable_periph_clk(WIRE_INTERFACE_ID); PIO_Configure( g_APinDescription[PIN_WIRE_SDA].pPort, g_APinDescription[PIN_WIRE_SDA].ulPinType, g_APinDescription[PIN_WIRE_SDA].ulPin, g_APinDescription[PIN_WIRE_SDA].ulPinConfiguration); PIO_Configure( g_APinDescription[PIN_WIRE_SCL].pPort, g_APinDescription[PIN_WIRE_SCL].ulPinType, g_APinDescription[PIN_WIRE_SCL].ulPin, g_APinDescription[PIN_WIRE_SCL].ulPinConfiguration);
NVIC_DisableIRQ(TWI1_IRQn); NVIC_ClearPendingIRQ(TWI1_IRQn); NVIC_SetPriority(TWI1_IRQn, 0); NVIC_EnableIRQ(TWI1_IRQn);
// Disable PDC channel WIRE_INTERFACE->TWI_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
TWI_ConfigureMaster(WIRE_INTERFACE, TWI_CLOCK, VARIANT_MCK); }
void setup() { SerialUSB.begin(115200); Serial.begin(115200); InitializeTWI(); }
void loop() { write(); delay(1000); //read(); //delay(1000); }
void TWI1_Handler() { int sr = WIRE_INTERFACE->TWI_SR; WIRE_INTERFACE->TWI_IDR = TWI_IDR_ENDTX | TWI_IDR_ENDRX; WIRE_INTERFACE->TWI_PTCR = TWI_PTCR_TXTDIS | TWI_PTCR_RXTDIS; WIRE_INTERFACE->TWI_CR = TWI_CR_STOP; if(didWeRead) { Serial.print("Read"); for(int i = 0; i < 8; i++) { Serial.print(" "); Serial.print(received[i]); } Serial.println(""); } else { long time = micros(); while(!(WIRE_INTERFACE->TWI_SR & TWI_SR_TXRDY)); time = micros() - time; Serial.print("Iterations: "); Serial.println(time); read(); } } EDIT: I'm building with make, so perhaps there are some differences (like #include <Arduino.h>)
|
|
|
|
|
3
|
Products / Arduino Due / Re: Arduino Due and Galaxy Nexus Problem with ADK
|
on: November 27, 2012, 07:37:33 am
|
|
Please let me know if you find a solution!
I've been playing around with modifications to the USBHost library to make it work better but I simply don't have the time to rewrite it properly! Turning on TRACE_USBHOST in Usb.h makes it work much much better, but at the expense of way too much debug output over serial. I believe it's simply a timing issue: the new Android devices are too slow, or the Due is too fast. Debugging slows down the sketch, thereby giving the Android time to switch to Accessory mode.
|
|
|
|
|
4
|
Products / Arduino Due / Re: Hardware Servo: Example Code
|
on: November 26, 2012, 04:28:46 am
|
I'm glad I could help  And thank you for a very good explanation of the parameters! I made PWM_CLOCK, PWM_PERIOD, PWM_DUTY_MIN and PWM_DUTY_MAX constants inside the library because they need no modification if you use the code as a servo library. But in your case and any similar ones it might be better to make them parameters to the writeMicros() method so the caller can set them freely. Also a rename of the methods might be proper, because if you modify PWM_CLOCK it will no longer be microseconds you write. initPWM() and writePWM, perhaps? Of course, PWM_DUTY_MIN and PWM_DUTY_MAX are only relevant for the servo implementation, you will most probably want to remove them completely or modify them to suit your needs. /Sebastian
|
|
|
|
|
5
|
Products / Arduino Due / Re: Timer Interrupts on Due
|
on: November 25, 2012, 09:09:35 am
|
Also, what are the pins in the table for? Good question! If I understood everything correctly, the pins in the table are where you could output the clock of that timer/counter if you wanted to use it for something else than internal software interrupts. Basically you can set up the hardware counter to output a clock signal. For example, TC0 channel 0 could be used to output a clock on the Arduino pin 2 or 13. So if you use TC0 channel 0 for your timer, you would not be able to output a clock on those pins (except using the frequency you set up the channel for). That is why it would be better to use TC1 channels 0, 1 or 2 primarily for this kind of interrupt, as their output is not mapped to any of the Arduino pins and therefore does not limit any of your physically mapped outputs.
|
|
|
|
|
6
|
Products / Arduino Due / Re: Arduino Due and ADK
|
on: November 17, 2012, 01:42:47 pm
|
|
OK, I hope this can help figure it out. Part of the problem, at least with the Note II, is timing. The error I get when debugging the USB host code is a timeout (error code 0xFF) on one of the USB packets. This doesn't happen if (for instance) I output a whole lot of serial data to slow the sketch down. It is not enough to add a delay() in the main loop, since the whole thing fails if we delay() too much as well. Adding a delay(50) between each call to Usb.Task() and a few delay(100) at strategic places inside USBHost::Task() makes it work pretty reliably. I haven't had the time to make it work well yet or I would post code.
Another issue is the fact that the USB code stops working if you soft-reset the Due, such as by opening the serial console after a sketch has started running. This can be worked around by uploading the sketch, then unplugging the Due and as fast as humanly possible after plugging it in, you open the debug console. I guess this works because you can actually soft-reset the Due before the USB initialization takes place, and therefore it doesn't try to initialize it twice.
If you have the phone connected to the Due and your sketch either crashes or your code is timed wrong, you might confuse the USB stack on the Android. This is only solved by rebooting. So if it stops working, you might get it running again by simply rebooting the Android. I power-cycle the Due between every run.
I ran a modified version of the ADK2012 sketch and library, compiled with the ADK2012 version of the IDE. This powered up the USB port even when running on external power, so there's nothing wrong with the hardware. There has to be a mistake somewhere in the library, I just don't have enough knowledge to find it!
|
|
|
|
|
7
|
Products / Arduino Due / Re: Arduino Due and ADK
|
on: November 16, 2012, 06:42:18 pm
|
|
Whitewater I have the exact same problem. Some times I get it to connected state and can transfer data successfully but then other times it just doesn't work. I haven't figured out what's wrong yet. I've had varying degrees of success on different devices. One sketch would work fine with bi-directional communication on one device but only unidirectional on the other. Another sketch would work on both. Today I only had one successful run out of perhaps ten or fifteen attempts with different very simple sketches. I always lose packets when I try sending them them too fast from the Due, like three in a row without any time between.
And the power is weird, isn't it? Of course it should power the USB port even if it's running on an external power source!
|
|
|
|
|
9
|
Products / Arduino Due / Re: SPI or SD library problem?
|
on: November 07, 2012, 08:33:37 am
|
I can't do the test because the example doesn't compile, besides I don't have an SD slot attached.. listfiles:26: error: variable or field 'printDirectory' declared void listfiles:26: error: 'File' was not declared in this scope listfiles:26: error: expected primary-expression before 'int' listfiles:23: error: 'File' does not name a type listfiles.ino: In function 'void setup()': listfiles:41: error: 'SD' was not declared in this scope listfiles:47: error: 'root' was not declared in this scope listfiles:47: error: 'SD' was not declared in this scope listfiles:49: error: 'printDirectory' was not declared in this scope listfiles.ino: At global scope: listfiles:59: error: variable or field 'printDirectory' declared void listfiles:59: error: 'File' was not declared in this scope listfiles:59: error: expected primary-expression before 'int'
|
|
|
|
|
10
|
Products / Arduino Due / Re: Arduino Due and ADK
|
on: November 07, 2012, 08:03:53 am
|
|
Does the phone get power from the Due, or nothing? How do you power the Due? I think it might be a power problem because my Desire S doesn't connect (only charge) when I'm powering the Due over computer USB while charging another phone from the same USB hub.
Another power problem: the USB host port doesn't seem to power up at all when I'm running the Due on 12V external power. Is there a call I need to make to enable the USB host power? And it gets better: while the host port appears to be dead, the programming port is powered; I can charge my phone over it! It's not supposed to power the programming port, right?
|
|
|
|
|
11
|
Products / Arduino Due / Re: Arduino Due Task Scheduler
|
on: November 07, 2012, 03:07:33 am
|
|
micnossub: yield() will let other competing threads execute and when they've had a go, continue this one as soon as possible.
It's a great ambition Paul!
I thought about the same problem with allocating stacks. The size limit isn't a problem, as you're exposing it in the start calls. If some library needs more, sooner or later that's going to pop up on their tutorials. Basically right now all the old libraries are used to having what... 4K or SRAM? If you gave every thread 4K you could have 24 threads on the Due (OK, probably more like 16 but anyway). Not many will do more than that and if they do, I think they'd know how to tweak their stack sizes. Hmm, it IS a problem on the AVR platforms, though...
I've done it differently in my application, sharing stack spaces and switching tasks upon the return of the last, ie return wait(20). Now that's basically trying to do the same thing you're doing but instead of putting "yield()" calls on strategic places in blocking libraries, I would need to rewrite them to be non-blocking. It's not impossible, every library I've seen can be rewritten since the interfaces are all wrapping code like "while(!done()) ; return result;". This is crazy to me, but that's the way it is. It's easier for beginners and that's what Arduino is all about.
So your way is better. Easier to get working quickly and more in line with the Arduino goal. I guess we could help each other out - I'll rewrite my application to use your library, then I can help you with testing and adding yield() calls to the other libraries I use: USBHost with ADK, Wire, and a bunch of Wire-based I2C drivers.
|
|
|
|
|
13
|
Products / Arduino Due / Re: Arduino Due Task Scheduler
|
on: November 06, 2012, 12:30:31 pm
|
Looking at how they've rewritten the delay() call to use yield() under the hood in the 1.5.1 release and the ambitions for 1.5.2 (on the mailing list) I'd say they're pretty serious about this library. I think it looks awesome and I'll start working with it as soon as I have the time to rewrite my home-brew scheduler! 
|
|
|
|
|
14
|
Products / Arduino Due / Re: Arduino Due and ADK
|
on: November 06, 2012, 11:32:47 am
|
It never occurred to me to try all of them before, but here goes: | Manufacturer | Name | Android | State | | HTC | Desire S | 2.3.7, CyanogenMod 7.1 | Works | | Asus | Transformer Prime TF201 | 4.1.1 | Works | | Samsung | Galaxy Tab 7" | 4.1.1, CyanogenMod nightly | Only charging | | Samsung | Galaxy Tab 2 10.1" | 4.0.4 | Works | | Samsung | Galaxy Note 2 | 4.1.1 | Only charging | | Google/Samsung | Galaxy Nexus | 4.? | Only charging |
EDIT: I don't think it's an Android version issue. I've heard the manufacturers can choose to disable the ADK feature (of course they can). I just never thought they would. Why?
|
|
|
|
|
15
|
Products / Arduino Due / Re: Arduino Due and ADK
|
on: November 06, 2012, 07:53:32 am
|
|
I have the Due working with ADK using both the example sketch and an application I wrote originally for the Mega ADK. The example sketch was just to compile and upload, then the phone would pop up a window on connection, giving me the option to open the URL given by the accessory code. I used a simple OTG cable connected to a normal USB charging cable to connect the Due to the phone.
It only worked on my HTC Desire S with CyanogenMod on it (Android 2.3.7 I think), the Google phone with Android 4 just started charging.
I'm having some trouble in my application too, spontaneous packet loss that I haven't had the time to figure out yet..
|
|
|
|
|