Reading SD card via USB - can you?
#1
Posted 20 November 2011 - 10:26 AM
#2
Posted 20 November 2011 - 12:52 PM
#3
Posted 25 December 2011 - 06:57 AM
#4
Posted 02 January 2012 - 09:23 PM
#5
Posted 03 January 2012 - 10:13 AM
Anyway on to the question. At the moment I am logging data on the bench at the end of each test I stop extract the SD card, plug into the computer to see if data has written correctly. This seems a rather clumsy way of accessing what is on the memory card. Is there an easy way of accessing the SD card with it left in situ, ideally via the USB port?
I have seen a project that could be of interest for you. I don't know the exact topic, but it was about simulating a keyboard (PC is the receiver and Netduino acts as a keyboard).
You could attach a little button etc. on you netduino to start the transmit. Then you read the file on the SD card and simulate key for key to send the whole file key for key to the PC, where for example word or the editor is opened.
Greets Markus
NeonMika.Webserver
> Control your N+ and write webservice methods easyily
> Receive data from you N+ (in XML or JSON)
> Browse the SD on your N+ directly in the browser and down - and upload files
If you need help with NeonMika.Webserver, please just leave a note in the thread and/or contact me via Skype
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Mistakes teach you important lessons. Every time you make one, you are one step closer to your goal. ----
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
#6
Posted 05 January 2012 - 08:40 PM
#7
Posted 05 January 2012 - 10:10 PM
#8
Posted 06 January 2012 - 01:41 AM
#9
Posted 10 February 2012 - 05:02 PM
the way i have been handling this sort of thing is to write to an array or a queue.
then you either have another thread sleeping, waking up, and doing the writes to the SD
or the other option is to test the length as you write to it and if the queue length hits a certain limit you do the write.
so you end up doing this:
1. the interrupt fires calling the sample logger function which writes the data to the queue or array
2. the write to disk thread is spinning in the background. every few seconds or 300ms it wakes up, checks the length of the queue and if its long enough it writes to disk and removes the items. you will need to vary your thread.sleep(xxx) calls accordingly. you will run out of memory quick if you are storing a data point with several parameters.
here is a snippet of code that i have been using to store the data in xml.
i created a class(deviceResult) that can return its data as an xml snippet (string) via the call to generateXMLnode()
that function takes the current time as a parameter cause it costs less memory to store the ticks as ints than it does to store the time in every result i enqueue. a quick calculation was worth it as a trade against speed cause i was running into memory limit problems doing the other way by storing the dateTime which is more bytes.
for the same reason it takes the GUID its assigned so that isnt being stored in every object in the queue.
in my case i am not making as many samples as you seem to be so i am getting away with generating the data to write within the time the fileStream is open. you may want to do that before entering the "using(FileStream..." section of code to increase throughput.
you may also want to play around with the last parameter of the new FileStream call cause that's your buffer size.
it may affect your write speed. i chose 128 cause i care more about using less memory than i do about speed since i am not sampling as often as you seem to be.
deviceResult dev = null; String res = ""; using (FileStream fs = new FileStream(resultsFileName, FileMode.Append, FileAccess.Write, FileShare.None, 128 )) { while ((dev = (deviceResult) resultsQueue.Dequeue()) != null) { res = dev.generateXMLnode( deviceGUID, startUpDateTime ); byte[] xmlBytes = Encoding.UTF8.GetBytes( res ); fs.Write( xmlBytes, 0, (int) xmlBytes.Length ); } fs.Close(); }
#10
Posted 10 February 2012 - 05:50 PM
have the rate of data logging controlled by either the lean of the bike or by the change in direction. it seems you care more about the telemetry data surrounding a turn than you do in the straight away.
so maybe the GPS or a gyro sensor could give feedback to a monitoring thread and that thread could in turn modify a variable that the logging thread uses to decide how fast to "fill" the results queue.
i wouldnt go for an interrupt approach on that.
i would use polling from that thread.
something like the following where "settings" is the reference to the global object holding the sampling parameters and is passed in when you create the object which has the method executed in your ThreadStart() call from main()
//Program.cs code public static void Main() { settings = new appSettings(); //initialize from SD card Debug.Print( "memory before obj instantiation: " + Debug.GC( false ) ); readSensor sen = new readSensor( settings ); checkForLean chk = new checkForLean( settings ); logToSD log = new logToSD( settings ); Debug.Print( "memory after obj instantiation: " + Debug.GC( false ) ); Thread senThread = new Thread( new ThreadStart( sen.Run ) ); Thread chkThread = new Thread( new ThreadStart( chk.Run ) ); Thread logThread = new Thread( new ThreadStart( log.Run ) ); // calling it Run like its JAVA ;) Debug.Print( "memory after threads created: " + Debug.GC( false ) ); senThread.Start(); chkThread.Start(); logThread.Start(); Debug.Print( "memory after threads started: " + Debug.GC( false ) ); //sen.Join(); // changed this recently to poll for crashed threads while (true) { if (!senThread.IsAlive) { senThread = new Thread( new ThreadStart( sen.Run ) ); senThread.Start(); //Thread.Sleep( 12000 ); //i needed this, you probably dont } if (!chkThread.IsAlive) { chkThread = new Thread( new ThreadStart( chk.Run ) ); chkThread.Start(); //Thread.Sleep( 12000 ); } if (!logThread.IsAlive) { logThread = new Thread( new ThreadStart( log.Run ) ); logThread.Start(); } Thread.Sleep(1000 * 180); // once every 3 minutes, we check if threads are still alive and restart them if necessary } }
so then you need to create your readSensor, checkForLean and logToSD classes and give them a constructor that takes an appSettings object and a method called Run() that is void Run(void) in signature
// check For Lean void Run() { float currentDirection = -1; float tempDirection = -1; while(true) { tempDirection = miracleOfGPS_unit.getDirection(); if (currentDirection varies way more than tempDirection) { settings.sampleRate = 20; } if (currentDirection varies a little more than tempDirection) { settings.sampleRate = 10; } if (currentDirection varies not much compared to tempDirection) { settings.sampleRate = 4; } // the above section can probably have more math and whatnot if you are so inclined to // calculate the derivatives of the change. after all you could put the sample queue in the // appSettings object and have access to it here. just remember you are multi-threading // and you may need to be thread safe or at least think about what can happen if its being modded as you read it currentDirection = tempDirection; Thread.Sleep(50); // gonna have to play around here and see what works 50 may be too fast or slow // should also be stored in settings like settings.checkForLeanSampleRate and loaded from SD card // so in the field you can just edit the settings.xml file on the SD card and not worry // about a recompile } }
//sample thread while(true) { // check samples and log to queue or array then sleep Thread.Sleep(1 / settings.sampleRate * 1000); //settings.sampleRate is in samples per second }
guess if you still need the interrupt code you could check the time elapsed against 1 / settings.sampleRate * 1000 * 10000 (or however you get from samples a second to ticks) and only log if enough time has passed.
yet another idea and should probably be classified as a "duct tape" solution:
if your runs on the track are close enough (by a few seconds) you may be able to more simply teach the course to the code.
for instance.
1. for 15 secs in straightaway so dont log.
2. for 8 secs in chicane - log heavily to memory
3 ....
success of that depends on the complexity of the course layout and the variance of your lap performances. i dont race so i have no idea if thats impossible.
i guess it was watching that Ayrton Senna documentary last night that is inspiring me to post on your thread. i agree with the other posters that its an awesome project.
#11
Posted 13 February 2012 - 02:06 AM
#12
Posted 13 February 2012 - 06:16 AM
#13
Posted 13 February 2012 - 07:03 AM
I like what @dougY has proposed, I'll try and implement that in a future code iteration.
To keep everyone out of suspenders, here is where we are keeping our code:
Codeplex Datalogger project
I've got a really old version of code there for MJ43, I just put my code up based on using the I2C implementation and forgot to add the SD card writing to it, so that'll get added in the next iteration.
I'm glad to see that this has got the thoughts and intrigue from other coders
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users