source: branches/atorf/personal playground/NXCDataLogging/LogToMemory.nxc @ 1065

Revision 872, 7.4 KB checked in by atorf, 5 years ago (diff)

NXCDataLogging: Initial check-in with small helper tools ("NXC Logging to Memory suite")…

Line 
1//#!C
2/*
3% The NXC Logging to Memory suite is a little collection of NXC functions which
4% help you log data points / samples to memory (RAM) first before writing them
5% to "disk" (flash).
6% Each sample will need 8 bytes of memory during logging, and about 27 bytes
7% of disk/flash-space for the CSV textfile to be written.
8% For a typical setting, this is about 4kb Memory for 10 secs logging and 15kb
9% flash space for the results file.
10%
11% Developed after posting this:
12% http://forums.nxtasy.org/index.php?showtopic=4798&view=findpost&p=36667
13%
14% Signature
15%   Author: Linus Atorf
16%   Date: 2010/02/18
17%   License: GPLv3
18%   Copyright: 2010, L. Atorf
19%
20%
21% ***********************************************************************************************
22% *  This file is part of the NXC Logging to Memory suite.                                      *
23% *                                                                                             *
24% *  The NXC Logging to Memory suite is free software: you can redistribute it and/or modify    *
25% *  it under the terms of the GNU General Public License as published by the Free Software     *
26% *  Foundation, either version 3 of the License, or (at your option) any later version.        *
27% *                                                                                             *
28% *  The NXC Logging to Memory suite is distributed in the hope that it will be useful,         *
29% *  but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS  *
30% *  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
31% *                                                                                             *
32% *  You should have received a copy of the GNU General Public License along with the           *
33% *  NXC Logging to Memory suite. If not, see <http://www.gnu.org/licenses/>.                   *
34% ***********************************************************************************************
35*/
36
37// include guards
38#ifndef __LOGTOMEMORY_NXC__
39#define __LOGTOMEMORY_NXC__
40
41
42#define LOGGING_SAMPLELENGTH 18    // in ms
43#define LOGGING_LOGDURATION 10000  // in ms
44
45#define LOGGING_MAXSAMPLES (LOGGING_LOGDURATION / LOGGING_SAMPLELENGTH)
46
47
48// needed to reserve space for exported CSV file
49// format used (roughly):
50// "10000000,-512,-512,-512,1"
51// pos,accX,accY,accZ,log was late<CRLF>
52#define LOGGING_CSVLINELENGTH 27
53
54// depending on what ReadSensorHTAccel returns (if negative values are allowed,
55// set this offset correction to 512)
56#define CONST_HTACCEL_OFFSET 512
57
58// bit-manipulation stuff
59#define CONST_BIT10 1024
60#define CONST_BIT20 1048576
61#define CONST_BIT31 2147483648     // 01000000...
62
63#define MASK_RIGHT10BIT 1023       // 00000...000...111...
64#define MASK_MIDDLE10BIT 1047552   // 00000...111...000...
65#define MASK_LEFT10BIT 1072693248  // 00111...000...000...
66
67
68
69
70long _LOGGING_Pos[LOGGING_MAXSAMPLES - 1];
71long _LOGGING_Acc[LOGGING_MAXSAMPLES - 1]; // 30 bit (3*10 bit for x,y,z) and 1 bit (minus-sign) if "log was late"
72
73long _LOGGING_LoggedValues = 0;
74
75long _LOGGING_LastSampleWaitTime = 0;
76long _LOGGING_LastLogTime = 0;
77
78// check this to see whether it was tried to log more values than possible (using available memory)...
79bool LOGGING_BufferOverflow = false;
80
81
82long MemoryBytesNeededForBuffer() {
83    // Returns memory needed in bytes for the logging-buffer
84   
85    return (LOGGING_MAXSAMPLES * 8);
86}//end function
87
88
89void WaitForNextSample() {
90    // Waits a "dynamic" amount of time until next "multiple" of LOGGING_SAMPLELENGTH
91    // is full, i.e. will always wait max 20ms. If already 18ms have passed, only 2 ms
92    // will be waited.
93
94
95    while((CurrentTick() - _LOGGING_LastSampleWaitTime) < LOGGING_SAMPLELENGTH) {
96        Wait(1);
97    }//end while
98   
99    _LOGGING_LastSampleWaitTime = CurrentTick();
100}//end void
101
102
103void LogToMemory(const long &pos, const long &accX, const long &accY, const long &accZ) {
104    // Logs the given values (position and accelerations) to memory buffer.
105    // Overflow-protection (if too many values were logged, LOGGING_BufferOverflow
106    // will be set to true).
107    // This function notices if a sample was logged late ("behind in schedule") and
108    // indicates it. Needs 8 bytes per sample.
109   
110    long tmp;
111
112    // memory left in buffer to log next value?
113    if (_LOGGING_LoggedValues >= (LOGGING_MAXSAMPLES - 1)) {
114        LOGGING_BufferOverflow = true;
115        return;
116    }//end if
117   
118
119    // prepare 30bit long with x, y, z
120    tmp = 0   + (accX + CONST_HTACCEL_OFFSET);
121    tmp = tmp * CONST_BIT10; // shift left
122    tmp = tmp + (accY + CONST_HTACCEL_OFFSET);
123    tmp = tmp * CONST_BIT10; // shift left
124    tmp = tmp + (accZ + CONST_HTACCEL_OFFSET);
125   
126    // if reading is late...
127    if((CurrentTick() - _LOGGING_LastLogTime) > LOGGING_SAMPLELENGTH) {
128        tmp = tmp + CONST_BIT31;
129    }// end if
130   
131    // finally store
132    _LOGGING_Acc[_LOGGING_LoggedValues] = tmp;
133   
134    // log pos, easy
135    _LOGGING_Pos[_LOGGING_LoggedValues] = pos;
136
137    // bookkeeping :-)
138    _LOGGING_LoggedValues++;
139    _LOGGING_LastLogTime = CurrentTick();
140}//end void
141
142
143void WriteLogToCSVFile(string filename) {
144    // Creates (and overwrites!) a CSV file with the datalogging results.
145    // Format is CSV (comma separated values), with this order:
146    // Position, AccelX, AccelY, AccelZ, was logging delayed (0 or 1)
147    // Example-line:
148    // 112334,0,-345,234,0
149    // Space needed will be about (somehow upper limit) 27 bytes per sample
150
151    long fileSize = 0;
152    long bytesWritten = 0;
153    byte fid = 0;
154    int x;
155    int y;
156    int z;
157    string tmpStr;
158    string tmpStr1;
159    string tmpStr2;
160    string tmpStr3;
161   
162    // delete if already exists!
163    DeleteFile(filename);
164
165    // prepare file...
166    fileSize = _LOGGING_LoggedValues * LOGGING_CSVLINELENGTH;
167    CreateFile(filename, fileSize, fid);
168
169    // for each sample
170    for(long i = 0; i < _LOGGING_LoggedValues; i++) {
171   
172        // write position
173        tmpStr = NumToStr(_LOGGING_Pos[i]);
174        WriteString(fid, tmpStr, bytesWritten)
175        WriteString(fid, ",", bytesWritten)
176       
177        // get 3 accelerations by ANDing bitmasks, do offset correction
178        x = (_LOGGING_Acc[i] & MASK_LEFT10BIT)   - CONST_HTACCEL_OFFSET;
179        y = (_LOGGING_Acc[i] & MASK_MIDDLE10BIT) - CONST_HTACCEL_OFFSET;
180        z = (_LOGGING_Acc[i] & MASK_RIGHT10BIT)  - CONST_HTACCEL_OFFSET;
181       
182        // convert to strings
183        tmpStr1 = NumToStr(x);
184        tmpStr2 = NumToStr(y);
185        tmpStr3 = NumToStr(z);
186       
187        // write accelerations
188        tmpStr = StrCat(tmpStr1, ",", tmpStr2, ",", tmpStr3, ",");
189        WriteString(fid, tmpStr, bytesWritten);
190       
191        // finally write if logging was late...
192        if((_LOGGING_Acc[i] & CONST_BIT31) > 0) {
193            WriteString(fid, "1", bytesWritten);
194        } else {
195            WriteString(fid, "0", bytesWritten);
196        }//end if
197       
198        // write linebreak (CRLF, Windows style)
199        tmpStr1 = Flatten(13);
200        tmpStr2 = Flatten(10);
201        tmpStr = StrCat(tmpStr1, tmpStr2);
202        WriteString(fid, tmpStr, bytesWritten);
203       
204    }//end for
205   
206    CloseFile(fid);
207
208}//end void
209
210
211/*
212// dummy-task main to check if it compiles
213task main() {
214
215    _LOGGING_Pos[0] = 0;
216   
217}//end task
218*/
219
220#endif
Note: See TracBrowser for help on using the repository browser.