Archive for category Projects

Inkbook Introduction

Inkbook is a new project I’ve started to replace Xournal for my needs. What I really want is a tightly integrated, full-features inking experience for Ubuntu.

What’s wrong with xournal?

Xournal is great. I use it all the time. However, there are a lot of really simple features I would like it to have. I took a look at the code, and it’s pretty hard to understand. The lack of good documentation means it’s not worth my time. There’s no sense in committing a ton of time trying to learn the code base, just to find out that an apparently simple feature is impossible to implement without restructuring the whole thing. So, I’m just restructuring the whole thing :).

I’ll start by going through all the things that I don’t like about Xournal.

Memory Usage

One of the biggest problems I have with Xournal is it’s memory usage. A typical 10 page Xournal document consumes around 300MB of RAM, and takes about 60 seconds to open. This is a big nuisance to me. I suspect that Xournal stores the whole document in memory, which is the cause.

Bitmaps

A lot of times I really want to paste some snippet into my notes. There is a Xournal patch for using bitmaps, and it’s not terrible, but the images render fuzzy and it’s difficult to scale and place them in the document. I usually end up exporting the whole thing to PDF for later reference. I’ve written a script which can copy parts of the screen to the clipboard (like the Adobe Reader snapshot tool), so I’d really like to be able to drop a bunch of images into a notebook and draw around them, write on them, etc.

Layers

I think that layers are a really useful tool, but it’s hard to use them in xournal. First of all, you have to select them from a drop down list at the bottom of the screen, not a list box. You can’t reorder them. And if you move to a lower layer, all the layers above it disappear.

Pen Options

Only three line widths and no fast-access colorwheel.

Shapes

Can only draw shapes by having the recognizer interpret them. Why not have shape tools that allow you to drop the shape and then resize, move around?

No lasso tool

Rectangular selection just doesn’t cut it for me. Especially when I have potato shaped drawings that I want to move around, without moving the text around it.

Inkbook

What I really want is a digital notebook. Inkbook aims to be just that. Inkbook is really a merger of features that I like from both Xournal and Inkscape, and an attempt to fix some of the problems I have with both. Here is a list of the features I’m currently focusing on.

  • very large documents
  • ability to organize notebooks (like folders)
  • ability to link individual pages to multiple notebooks
  • multiple layers per page
  • multiple page sizes
  • continuous range of brush sizes
  • continuous color picking
  • bitmap cut & paste
  • grouping of paths
  • objects (shapes)
  • collaboration (openbook module?)

Very large documents and Organization

I want to be able to have several dozens of pages in a document, which basically means that the entire document can’t be stored in memory. Therefore, I’m attemping to store the data an a sqlite database. This also addresses the desire to have better organizational facilities. I’m implementing separate database objects for notebooks, pages, layers, objects, and paths.

A notebook is an ordered list of notebooks and an ordered list of pages (i.e. a folder). A page is an ordered list of layers. A layer is an ordered list of objects. An object is an ordered list of objects, images, or paths. A path is an ordered list of drawing primitives (most likely a one-to-one mapping to the cairo API).

Organization and View

For organizing notebooks, I plan to have a triew-view (i.e. directory tree). I’ll have a thumbnail page view which shows the current pages and those near it, and allows for scrolling through the whole notebook. This will be a custom widget which renders each of the pages via their thubmail image. I’ll have a list-view to organize layers on the page. The list view will also show list complex objects so they can be easily selected and edited (but it wont display any information about handdrawn paths, as there will be a large number of these). The main view will display a viewport of the page.

Current Progress

I’ve got a proof-of-concept running with the sqlite database file backend and working views the notebook organization and layers. I’ve got a proof-of-concept for the thumbnail view but it needs more work. It’s written in C++ and meant to be very easy to understand and extend. I’m using Gtkmm3 (unstable) because it’s GTK, but it’s C++, and it has cairo as the native API. Here’s a screenshot:

Inkbook Screenshot

Inkbook Screenshot

1 Comment

TxDuino: Configuration Builder in WxWidgets

In relation to the TxDuino (somewhat documented here), I wrote a C++ class to ease the interfacing with the device. That code was posted here. In this post, I am sharing a program that can be used to easily discover and save the configuration of the saturation points of the different actuators on a vehicle. The program is written using the wxWidgets toolkit so *should* be compatible with any wx-supported operating system. Of course, at this point in time I still haven’t updated the TxDuino class with linux implementations yet, but hopefully that will happen soon.

The saturation points are the raw commands that correspond to the extreme edges of the actuators range. For instance, if the actuator is a servo, then the minimum saturation point is the minimum command that the servo can actually achieve. If a command lower than that is sent, then the servo will constantly jitter as it cannot actually achieve that rotation. By setting the saturation points, normalized commands (percentages) can be sent to the device using the TxDuino::setPercent() function.

A screenshot of the program in action is below:

Actuator Configuration Tester

Actuator Configuration Tester

You can connect to the device by entering the device name in the text field at the top and clicking “Connect” (or pressing enter). Once the device is connected (success or failure will be reported in the console at the bottom), then commands can start being sent. You can start sending commands by clicking “Continue” or stop at any time by clicking “Pause”. Note that “pausing” won’t stop your vehicle from doing something retarded, the vehicle’s actuators will just be stuck in the last commanded state. If the program is not paused, then every time you change one of the values in the spin controls, then that new value is sent as the current command.

To discover the value of the minimum saturation point of one of the actuators, start by clicking on the spin control for that channel, setting it to zero, and hitting enter (this makes the control think it has changed whether it has or not so the value is sent to that channel). If the actuator is saturated (on a servo, if it’s making noise and/or jittering but not correcting itself) then raise the value by one unit. Keep raising the value until the actuator is no longer saturated. Repeat for the max saturation point and the neutral point. The neutral point is the point corresponding to 0%. For a servo this is most likely near the center of it’s range. For a speed controller, it should be the same as the minimum saturation.

A windows binary of this program can be downloaded here: Tester .
The source can be downloaded here: TxDuino Actuator Configuration Tester.

No Comments

TxDuino: C++ classes (windows)

In order to make interfacing with the TxDuino as easy as possible, I wrote a little c++ class to take care of all the heavy lifting. You connect to a TxDuino device by creating a TxDuino object. The constructor accepts a device name. In windows that looks like “\.COM8” (my arduino is installed on COM port 8). In linux it’ll look something like “/dev/ttyS2” except that I haven’t gotten around to implementing the linux part of this class yet.

The class, along with the supporting classes and test program are included here: TxDuino Class Source.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/**
 *  file       TxDuino.h
 *  date:      Oct 27, 2009
 *  brief:
 *
 *  detail:
 */
 
#ifndef CTXDUINO_H_
#define CTXDUINO_H_
 
 
#include <vector>
#include <string>
 
#include "types.h"
 
 
namespace txduino
{
 
 
/**
 *  brief  operating system dependendant implementation structure
 */
struct STxDuinoImpl;
 
/**
 *  brief Class encapsulating the interface / API for communicating with one
 *  TxDuino device. The TxDuino sends a standard RC PPM signal encoding
 *  commands for up to 8 PWM channels (servos, engine controllers).
 *
 *  The magnitude of each channel is divided into 250 discrete segments.
 *  Exactly how those segments are interpreted by the actuators is determined
 *  by the configuration of this object.
 *
 *  note: channels are zero indexed
 *
 *  todo   add a constructor that accepts a csv file with the saturations and
 *          neutral points that can be generated from the test program
 */
class CTxDuino
{
    private:
        STxDuinoImpl*   m_osInfo;   /// pointer to os-dependant implementation
        std::string     m_devName;  /// system device name,
                                    /// i.e. "\.COM2", "/dev/tty2"
 
        u8          m_chan      [9];    /// value for each channel [0,250]
        u8          m_neutral   [8];    /// the "center" for each actuator
        u8          m_minsat    [8];    /// the minimum value for each channel
        u8          m_maxsat    [8];    /// the maximum value for each channel
 
 
    public:
        /**
         *  brief  Constructs a new TxDuino object serving as an interface
         *          into on particular TxDuino device.
         *  param  strDevice   device string, i.e. "\.COM2", "/dev/tty2"
         */
        CTxDuino( std::string strDevice );
 
 
        /**
         *  brief  cleans up OS resources reserved for this serial connection
         */
        virtual ~CTxDuino();
 
 
        /**
         *  brief  sends the current channel definitions to the device
         */
        void send();
 
 
        /**
         *  brief  sets the value of an actuator as a percent of it's viable
         *          range.
         *  param  chan        the channel to set
         *  param  percent     -100% < percent < 100%; value to set channel to
         */
        void setPercent( s32 chan, f64 percent );
 
 
        /**
         *  brief  returns the percent value the indicated actuator is set to,
         *          note: if the neutral point is equal to one of the saturation
         *          points this value may be unreliable
         *  param  chan        the channel to get
         *  return percent value of actuator on indicated channel
         */
        f64 getPercent( s32 chan );
 
 
        /**
         *  brief  sets the raw value of the actuator pulse width
         *  param  chan        the channel to set
         *  param  value      0 < value < 250; value to set channel to
         */
        void setRaw( s32 chan, u8 value );
 
 
        /**
         *  brief  returns the raw value the indicated actuator is set to
         *  param  chan        the channel to get
         *  return a value between 0 and 250 indicated the pulse length for
         *          that actuator (multiply by 4us and add 700us to get the
         *          actual pulse length)
         */
        u8 getRaw( s32 chan );
 
 
 
 
        /**
         *  brief  sets the raw value of the actuator pulse width corresponding
         *          to a neutral state of that actuator
         *  param  chan        the channel to set
         *  param  value      0 < value < 250; value to set channel to
         */
        void setNeutral( s32 chan, u8 value );
 
 
        /**
         *  brief  returns the raw value corresponding to a neutral state of
         *          the indicated actuator
         *  param  chan        the channel to get
         *  return a value between 0 and 250 indicated the pulse length for
         *          that actuator (multiply by 4us and add 700us to get the
         *          actual pulse length)
         */
        u8 getNeutral( s32 chan );
 
 
 
 
        /**
         *  brief  sets the raw value of the actuator pulse width corresponding
         *          to the minimum state of the indicated actuator
         *  param  chan        the channel to set
         *  param  value      0 < value < 250; value to set channel to
         */
        void setMinSat( s32 chan, u8 value );
 
 
        /**
         *  brief  returns the raw value corresponding to a minimum state of
         *          the indicated actuator
         *  param  chan        the channel to get
         *  return a value between 0 and 250 indicated the pulse length for
         *          that actuator (multiply by 4us and add 700us to get the
         *          actual pulse length)
         */
        u8 getMinSat( s32 chan );
 
 
 
 
        /**
         *  brief  sets the raw value of the actuator pulse width corresponding
         *          to the maximum state of the indicated actuator
         *  param  chan        the channel to set
         *  param  value      0 < value < 250; value to set channel to
         */
        void setMaxSat( s32 chan, u8 value );
 
 
        /**
         *  brief  returns the raw value corresponding to a maximum state of
         *          the indicated actuator
         *  param  chan        the channel to get
         *  return a value between 0 and 250 indicated the pulse length for
         *          that actuator (multiply by 4us and add 700us to get the
         *          actual pulse length)
         */
        u8 getMaxSat( s32 chan );
 
 
        /**
         *  brief  return the device name that was used to connect to this
         *          txduino
         */
        std::string getName();
 
};
 
}
 
#endif /* CTXDUINO_H_ */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
/**
 *  file       CTxDuino.cpp
 *  date:      Oct 27, 2009
 *  brief:
 *
 *  detail:
 */
 
#include "CTxDuino.h"
#include "compile.h"
 
#include <iostream>
#include <iomanip>
#include <sstream>
#include <cmath>
 
#include "IllegalArgumentException.h"
#include "IOException.h"
 
#ifdef TXD_MINGW
#include <windows.h>
#endif
 
namespace txduino
{
 
 
 
#ifdef TXD_MINGW
struct STxDuinoImpl
{
    HANDLE hComPort;    /// handle to the opened COM device
};
#endif
 
 
#ifdef TXD_LINUX
struct STxDuinoImpl
{
    FILE hSerialFile;
};
#endif
 
 
 
 
 
 
/**
 *  The initial state of the individual actuators is initialized as follows
 *
 *  verbatim
 *      minimum saturation: 0
 *                 neutral: 125
 *      maximum saturation: 250
 *                   value: 125
 *  endverbatim
 *
 *  Note that this is probably not appropriate for your system. Many of the
 *  servos that we've used have minimum saturations around 10 and maximum
 *  saturations around 240. Use the actuator test program to determine what
 *  these values should be.
 */
CTxDuino::CTxDuino( std::string strDevice )
{
    using std::cout;
    using std::endl;
    using std::stringstream;
 
    // intiialize all the arrays
    for( int i=0; i < 8; i++ )
    {
        m_chan      [i] = 125;
        m_minsat    [i] = 0;
        m_maxsat    [i] = 250;
        m_neutral   [i] = 125;
    }
 
    // stop byte
    m_chan[8]   = 0xFF;
 
    // initialize the OS dependant information
    m_osInfo    = new STxDuinoImpl();
 
 
/* ----------------------------------------------------------------------------
 * Windows Specific Implementation:
 * ---------------------------------------------------------------------------*/
 
#ifdef TXD_MINGW
    // open the file using the windows API
    m_osInfo->hComPort  =
    CreateFile( strDevice.c_str(),          // file name
        GENERIC_READ | GENERIC_WRITE,       // access mode: read and write
        FILE_SHARE_READ|FILE_SHARE_WRITE,   // (sharing)
        NULL,                               // (security) 0: none
        OPEN_EXISTING,                      // (creation) i.e. don't make it
        0,                                  // (overlapped operation)
        NULL);                              // no template file
 
    // check to make sure the file open succeeded
    if( m_osInfo->hComPort == INVALID_HANDLE_VALUE )
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid Device Name: " << strDevice;
        throw IllegalArgumentException(message.str());
    }
 
    // get the current settings on the com port
    DCB dcb;
    GetCommState( m_osInfo->hComPort, &dcb );
 
    // change the settings, the TxDuino uses a BAUD rate of 9600
    dcb.fBinary     =   1;
    dcb.BaudRate    =   CBR_9600;
    dcb.Parity      =   NOPARITY;
    dcb.ByteSize    =   8;
    dcb.StopBits    =   ONESTOPBIT;
 
    // set the new settings for the port
    SetCommState( m_osInfo->hComPort, &dcb );
#endif
 
 
}
 
 
 
CTxDuino::~CTxDuino()
{
 
/* ----------------------------------------------------------------------------
 * Windows Specific Implementation:
 * ---------------------------------------------------------------------------*/
 
#ifdef TXD_MINGW
    // close the device if it's open
    if( m_osInfo->hComPort != INVALID_HANDLE_VALUE )
        CloseHandle( m_osInfo->hComPort );
#endif
 
delete m_osInfo;
 
}
 
 
 
void CTxDuino::send()
{
    using std::stringstream;
 
 
    // ensure that the last byte of the packet is the stop byte
    m_chan[8] = 0xFF;
 
 
/* ----------------------------------------------------------------------------
 * Windows Specific Implementation:
 * ---------------------------------------------------------------------------*/
 
#ifdef TXD_MINGW
    DWORD bytesWritten;
 
    BOOL retVal =
    WriteFile(  m_osInfo->hComPort, // output handle
                m_chan,             // buffer of bytes to send
                9,                  // number of bytes to send from buffer
                &bytesWritten,      // pointer to a word that receives number of
                                    // bytes written
                NULL);              // pointer to an OVERLAPPED struct
 
    if( bytesWritten != 9 )
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Bytes written to device less than expected: "
                << bytesWritten << ", expecting 9";
        throw IOException(message.str());
    }
 
    if( retVal == 0 )
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Writing to device failed; error code: " << GetLastError();
        throw IOException(message.str());
    }
#endif
 
}
 
 
 
/**
 *  If the percent is positive, the raw value is calculated as follows
 *
 *  verbatim
 *      raw = neutral + (max - neutral) * percent
 *  endverbatim
 *
 *  if the percent is negative, the raw value is calculated as follows
 *
 *  verbatim
 *      raw = neutral - (neutral - min) * percent
 *  endverbatim
 */
void CTxDuino::setPercent( s32 chan, f64 percent )
{
    using std::stringstream;
 
    if(chan < 0 || chan > 7)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid channel number: " << chan << HERE
                << "valid channels are 0-7";
    }
 
    if(percent > 0)
    {
        m_chan[chan] = (u8) (m_neutral[chan] +
                    ( m_maxsat[chan] - m_neutral[chan]) * percent );
    }
 
    else
    {
        m_chan[chan] = (u8) (m_neutral[chan] -
                    ( m_minsat[chan] - m_neutral[chan]) * percent );
    }
}
 
 
 
/**
 *  If the value is strictly less than the neutral value then the percent value
 *  is calculated by
 *
 *  verbatim
 *      percent = -( neutral - value ) / (neutral - min);
 *  endverbatim
 *
 *  If the value is strictly greater than the neutral value then the percent
 *  value is calculated by
 *
 *  verbatim
 *      percent = ( value - neutral ) / (max - neutral);
 *  endverbatim
 *
 *  If the value is equal to the neutral value then the percent value is zero.
 */
f64 CTxDuino::getPercent( s32 chan )
{
    using std::stringstream;
 
    if(chan < 0 || chan > 7)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid channel number: " << chan << HERE
                << "valid channels are 0-7";
    }
 
    if( m_chan[chan] < m_neutral[chan] )
    {
        return (double)(-(m_neutral[chan] - m_chan[chan])) /
                    (m_neutral[chan] - m_minsat[chan]);
    }
 
    else if( m_chan[chan] > m_neutral[chan] )
    {
        return (double)(m_chan[chan] - m_neutral[chan]) /
                    (m_maxsat[chan] - m_neutral[chan]);
    }
 
    else
    {
        return 0.0;
    }
}
 
 
 
void CTxDuino::setRaw( s32 chan, u8 value )
{
    using std::stringstream;
 
    if(chan < 0 || chan > 7)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid channel number: " << chan << HERE
                << "valid channels are 0-7";
    }
 
    if(value > 250)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid value: " << value << HERE
                << "valid channels are 0-250";
    }
 
    m_chan[chan] = value;
}
 
 
 
u8 CTxDuino::getRaw( s32 chan )
{
    using std::stringstream;
 
    if(chan < 0 || chan > 7)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid channel number: " << chan << HERE
                << "valid channels are 0-7";
    }
 
    return m_chan[chan];
}
 
 
 
void CTxDuino::setNeutral( s32 chan, u8 value )
{
    using std::stringstream;
 
    if(chan < 0 || chan > 7)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid channel number: " << chan << HERE
                << "valid channels are 0-7";
    }
 
    if(value > 250)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid value: " << value << HERE
                << "valid channels are 0-250";
    }
 
    m_neutral[chan] = value;
}
 
 
 
u8 CTxDuino::getNeutral( s32 chan )
{
    using std::stringstream;
 
    if(chan < 0 || chan > 7)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid channel number: " << chan << HERE
                << "valid channels are 0-7";
    }
 
    return m_neutral[chan];
}
 
 
 
void CTxDuino::setMinSat( s32 chan, u8 value )
{
    using std::stringstream;
 
    if(chan < 0 || chan > 7)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid channel number: " << chan << HERE
                << "valid channels are 0-7";
    }
 
    if(value > 250)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid value: " << value << HERE
                << "valid channels are 0-250";
    }
 
    m_minsat[chan] = value;
}
 
 
 
u8 CTxDuino::getMinSat( s32 chan )
{
    using std::stringstream;
 
    if(chan < 0 || chan > 7)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid channel number: " << chan << HERE
                << "valid channels are 0-7";
    }
 
    return m_minsat[chan];
}
 
 
 
void CTxDuino::setMaxSat( s32 chan, u8 value )
{
    using std::stringstream;
 
    if(chan < 0 || chan > 7)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid channel number: " << chan << HERE
                << "valid channels are 0-7";
    }
 
    if(value > 250)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid value: " << value << HERE
                << "valid channels are 0-250";
    }
 
    m_maxsat[chan] = value;
}
 
 
 
u8 CTxDuino::getMaxSat( s32 chan )
{
    using std::stringstream;
 
    if(chan < 0 || chan > 7)
    {
        stringstream message( stringstream::in | stringstream::out );
        message << "Invalid channel number: " << chan << HERE
                << "valid channels are 0-7";
    }
 
    return m_maxsat[chan];
}
 
 
 
std::string CTxDuino::getName()
{
    return m_devName;
}
 
 
 
 
 
 
}

A re-write of the serialTest.exe program that sends sinusoidal commands to the plane using this new class demonstrates its use.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
 * 	file		serialTest.cpp
 *  date:      Oct 27, 2009
 *  brief:
 *
 *  detail:
 *  This is a simple test program that demonstrates how to connect to and
 *  write commands to the arduino transmitter interface using windows.
 *
 *  the TxDuino is an interface into the futaba FP-TP-FM transmitter module,
 *  which accepts an RC PPM input. This signal contains a maximum of 8
 *  servo channels.
 */
 
#include <iostream>
#include <iomanip>
#include <cmath>
 
#include "CTxDuino.h"
#include "constants.h"
 
using namespace std;
using namespace txduino;
 
int main( int argc, char** argv )
{
    // check to ensure that the command line included a device to open
    if( argc < 2 )
    {
        cout << "Usage: serialTest.exe [Device Name]n"
                "   where [Device Name] is the name of the COM port file onn "
                "   windows (i.e. \\.\COM8), or the name of the serialn "
                "   device on *nix (i.e. /dev/tty8)n" << endl;
 
        return -1;
    }
 
    // grab a pointer to the device to open
    char*       strDevName = argv[1];
 
    // create the txduino device
    CTxDuino tx(strDevName);
 
    // send a sinusoidal input on all channels (except for channel 3, which is
    // usually the throttle) for 10 seconds
    for(int i=0; i < 1000; i++)
    {
        for(int j=0; j < 8; j++)
            tx.setRaw(j, (unsigned char)
                            (125.0 + 75.0 * sin( 2.0 * PI * i / 100.0 )) );
 
        tx.setRaw(2, 0);
 
        for(int j=0; j < 8; j++)
            cout << setw(3) << (int)tx.getRaw(j) << " | ";
        cout << endl;
 
        tx.send();
 
#ifdef TXD_MIGNW
        Sleep(1);
#endif
 
#ifdef TXD_LINUX
        usleep(0.001);
#endif
    }
 
 
    return 0;
}

No Comments