From 13489c50c3abe76e1fa312d6af6325947d97fb82 Mon Sep 17 00:00:00 2001 From: Thomas Pietrzak Date: Tue, 11 Sep 2012 10:36:36 +0000 Subject: [PATCH] Add support for angles on hardware, fixed PWM frequency git-svn-id: svn+ssh://thomaspietrzak.com/var/svn/rep@99 47cf9a05-e0a8-4ed5-9e9b-101a649bc004 --- Arduino/wristbandTactons/wristbandTactons.ino | 48 ++++++++++++++-- TactonDebug/MagicCircle/magiccircle.cpp | 5 +- TactonDebug/TactonDebug.suo | Bin 36864 -> 39936 bytes TactonDebug/TactonDebug/tactondebug.cpp | 2 + TactonLibrary.suo | Bin 28160 -> 28160 bytes TactonPlayer/Tacton.hpp | 52 ++++++++++-------- TactonPlayer/TactonPlayer.cpp | 36 ++++++++++++ TactonPlayer/TactonPlayer.hpp | 40 +++++++++----- 8 files changed, 139 insertions(+), 44 deletions(-) diff --git a/Arduino/wristbandTactons/wristbandTactons.ino b/Arduino/wristbandTactons/wristbandTactons.ino index 0e4e14b..a0e4df7 100644 --- a/Arduino/wristbandTactons/wristbandTactons.ino +++ b/Arduino/wristbandTactons/wristbandTactons.ino @@ -29,13 +29,13 @@ void loop() { byte index; unsigned long timestamp; - unsigned int freq; + unsigned int param; if (Serial.available() > 0) { if (command == 0) command = Serial.read(); - switch(command) + switch(command) { //set the timestamp to 0, and watch for scheduled tactons case 'S': @@ -154,12 +154,52 @@ void loop() case 'F': if (Serial.available() >= 2) { - freq = (((unsigned long)Serial.read()) << 8) | \ + param = (((unsigned long)Serial.read()) << 8) | \ (((unsigned long)Serial.read())); - manager.setFrequency(freq); + manager.setFrequency(param); command = 0; } break; + //sets an angle in degrees + case 'a': + if (Serial.available() >= 2) + { + param = (((unsigned long)Serial.read()) << 8) | \ + (((unsigned long)Serial.read())); + manager.setAngle(param); + command = 0; + } + break; + //sets a series on angles + // sNDnA1A2...AN + // N = nb angles (1 byte) + // D = duration in ms of each frame (2 bytes) + // n = number of frames (2 bytes) + // A1, A2, ..., AN : angles (2 bytes per tactor) + case 's': + if (nbf == 0 && Serial.available() >= 1) + nbf = (unsigned int) Serial.read(); + if (nbf > 0) + { + //DO NOT OVERFLOW max(nbf): 60 + while (posbuf < 2 * nbf + 4 && Serial.available() > 0) + { + buffer[posbuf] = Serial.read(); + //Serial.print(buffer[posbuf], HEX); + posbuf++; + } + if (posbuf >= 2 * nbf + 4) + { + manager.setAngleSequence(nbf, \ + (buffer[0] << 8) | buffer[1], \ + (buffer[2] << 8) | buffer[3], \ + buffer + 4); + posbuf = 0; + command = 0; + nbf = 0; + } + } + break; //stop any vibration case 'B': manager.stop(); diff --git a/TactonDebug/MagicCircle/magiccircle.cpp b/TactonDebug/MagicCircle/magiccircle.cpp index ed257ea..8b883c7 100644 --- a/TactonDebug/MagicCircle/magiccircle.cpp +++ b/TactonDebug/MagicCircle/magiccircle.cpp @@ -77,7 +77,7 @@ void MagicCircle::setDirection(const QString &direction) void MagicCircle::setSpeed(int speed) { - _timer.setInterval(_stepsize / speed * 1000); + _timer.setInterval(_stepsize / speed * 1000.0); } void MagicCircle::setResolution(int res) @@ -93,6 +93,9 @@ void MagicCircle::setFrequency(int frequency) void MagicCircle::tactileFeedback(float angle) { + _tactonPlayer->playAngle(angle);// * M_PI / 180); + return; + unsigned char amplitudes[4]; memset(amplitudes, 0, 4); diff --git a/TactonDebug/TactonDebug.suo b/TactonDebug/TactonDebug.suo index d16f968764d865f25a9fda3e3707072f7f1aa49f..a15620dbcdde91a5703ef73338db4931dcc47551 100644 GIT binary patch delta 2511 zcmds2eN0nV6u+fyPBPIr zK6>_H79$KNTQ*~m=Ld6ac1jjM7$at8n_J@C5|f!_Su&P5hjiz4#YHp!a_*1ao8LRX zd(V64oZkDpy}n+KZ-_H6%8{uEA*&Em!C;U@Ch{zV60sWb9D<$KqeT;hNsc7G2nYFy z0z@H#eW4g_2_hZQZ5Z`)ZT#Lnj`Ta7jEj4mLmh+!!Lu>%qH_>YiC~yYLC;M7IizL| z+>P7GS0HVOV|LEAQB*cGiVQF?rwk6yQ-V^W_KSB=6HJSEF9kc3OJGDIg$)~JxN?Xiw7pR!2#$X{eEAvW{<6feE6hc?lPkP-`)QeTC^0)_ zbHcnY7mZ(G3RWGWV(r@{CtlO^RGqE*y7B1y9eG0LH^n;~F1sSotCVK4gvCj$gSDs8 zoORDAH2`;Pc> zxS-kc>6#4mwGu5!BYKiY6eI(ma*{%FLOdOr9J`LlkZD6cEixH)Eg~0%Aj2=&o=ei< zoFp0ebY`^E<#^tkt29=+EiV5$AJ{$H;V>!4M1 zf~qkRuB)ZI3PO`=pt6+E(JYN!D*81>-2GNf+o_jD?Hg`fs03%W2!0l3!ayb$YU|^{ z)2xnF5eIP+3$YV5i6JwH3AFBF7|(f>r%PS*h;M|8t7bnO4ObTAsSBt?X19G8#RS&1 zM{rr~g|y~b|3w5`T)2Wd1x=gQMp5ix%9(afY>MW9tEG+MzNq3+r(yT}>~4dEk(iS> zaK54qbRIACEt9}^uf)TSx&rXiQrOZdi7*i-7-$RfUeGMr2pjAB{7uyn2g5%M%a0%= z0X8-51z*Dmj4YJ#_!J>y@cW`+`!@8g^$W9^9+G zEoPNB-PR((eJ8q0&{_6o#5URrllAAp-x|-#2qry|Fx4_e*+apr4Px+?&Vi1yTVl?1 z1oF!{5%QUAkTLj1-w$1D_|V~$@Seh{_uzBkdOT@Drp@c6@BmQWpkS~)mx>Bq7;1cl zJp|y{cL2(1b2w@3!$M_Hs2n&^odu5aSby~t{85t!4f#b?g5`M=_SyGS&#;zea7jl@H?;bq5;YDhB#HpBpb$4gM& e90#NILcG{Cym(x!lMtJ+5(ZYbF~j>c+&=-3S}9Nf delta 1232 zcma*mdrVtZ90%}w?!DX=TuZu^rZ6Q4b&fH@s)Ut?YhevTtPb|jC}cEIL>VsV3I(=F zrx=+dJo+VWAqztmi6)COE;8nDR)!|q7+G+C7$sAOk1yui!L0`pCZQ6iZL!pq(+3>QV z7}l5~pRta;D%Ts|Way5|!dUWVpQ&2DX=)eQak>7!{Y-j<5}en|i}9CKYDybQqBa_B z>*R&CU#W1)sm4Z8ZMIBq`nGJ_tfTv(=nf(J$OZqMGPD1{rot1dJvpt(R}ath9iJXZ z8|HO&NuRd~GpAzb-&mOGPO2S@f<@5FQKqiCaBQiwJkYRF`d`!-f5%LK+ zPd+6GWSL_xQt%zQOlHUx@+%1{JtS!5u-L*I06uU(ndr;KJ2T=hK|s!4^d z(}*O|z&n;Zb9J=nN|7jH*m>ZVj;(y-IK2{M+riUtd6L2@GFx@NJg=|73s;;0$)Xmk z)8l3Tj%Gp3QpPHe#r@PZK@2}=YO%jjQ}P5Zh!%OFWECGlgB%m+@buxW+T?J`^fm)? zgwI2J)RZVoE|m)8wmIR={{kaht&GE={blm?f<%S{r-<40&x3awaU*{NW}R`Ga&F)9 zJle;Vb*XF!ht}9)7#)Zw0uf0B3Cc0grSK>1k2CbHH(~FNI0U;S)KwH-#@kaUfdfTtlgg%Jl>1sPQ55h>1MgI(z`JKG{Et>CALs%iBwBC+ z#p=f}_EHX9YR6sm2uqN2w>L6uKe`iL4;RVirYQk)Wlmf#Fkvb)9(-jfYelrC5q_&y zj%vBh@cz?gnBRVl4MLZmhW@lB*?+W^$7n?cWni;EZ7--(YB3U-=)4sG int TactonDebug::MaxFrequency = 400; int TactonDebug::MaxAmplitude = 255; int TactonDebug::MaxDuration = 2000; @@ -14,6 +15,7 @@ TactonDebug::TactonDebug(QWidget *parent, Qt::WFlags flags) catch(...) { _tactonPlayer = NULL; + qDebug() << "No wristband found"; } setupUi(this); diff --git a/TactonLibrary.suo b/TactonLibrary.suo index e0587c7bb029e66b609ec372846e0e3c1e8fe524..74821d47612720cb02978479b9aed2f9ec77af1b 100644 GIT binary patch delta 725 zcmcJM-)oX#6vy93U#DyieVx-`krp<@Rb)S0X_6(=Fqc+NV=o(KW5lx2#=9YOk@Vv( zH1^FdB52SGV^EvVu67YdGIkTS>So|&?An0@K~T@z68r}`aNsUDr=gHMbu11zJ zd|U3dqbwEZG=H%JA9xpS=wb@(E{@{_mcLnGgSSI6#I*85*8*w7z*>!rXj>?x?kEB} zU)dDkJ4pvqx>{5!S(Z(js~=wlLyxBY*b`3Ef=i_qdRWg+^j1QwP{0x%N5SQz=T2G( zR=g2tj|P<-XU3V!X86SfZiyB=^g59C43|%>D>Vi-*7Qpor?m>Cy-sX-_K^~%#vY)a zveO@DFDW#~S{tQ-IMKLU2pYj?Cy^KRw@@mDiV8tKOEX+@K`r40B0Oy}&QW3(Di7I7ba(WmW%%9iPgmB)XT;EfPP1cuMyaik8yV-3tLQ! zT%sNIxE_^c9`!4E@(kPK_t<4js_V=S4>DxNQYHtRs8R1{B*6vnUi4w>#%?SOoxptB zjW<>!;jo?PqYjZ*;DGoIlOslI9F6m+-ZajQd7yWO*$4IEPRh$hMwQ{eYpnF$wa?1` U;Ro}>ZCFW8AZ2&bCz%QI2guS5EdT%j delta 731 zcmZp;!`N_#aYGIZ+ku!HX^-+Z7qJ9#^D_Pi0ucrV1`s{@B8$rAFZ=;aJi^USFuf2loy`-$8Uw;y$UzuN`*PI&sI?@yh*Zci#>qX>X0#K9;td1Lro#yQZClVj|d92noqngMhI-(<#6 z@yQ!<8YU}5b1> 8); + buffer[2] = (unsigned char)(angle & 0x000000ff); + _comport->WriteData(buffer, 3); + delete[] buffer; +} + +//plays an animation alterning a series of angles +void TactonPlayer::playAngleSequence(unsigned char nbangles, unsigned int frameduration, unsigned int nbframes, unsigned int *angles) +{ + if (!_comport) + return; + + unsigned char *buffer = new unsigned char[6 + 2 * nbangles]; + buffer[0] = 's'; + buffer[1] = nbangles; + buffer[2] = (unsigned char)((frameduration & 0x0000ff00) >> 8); + buffer[3] = (unsigned char)(frameduration & 0x000000ff); + buffer[4] = (unsigned char)((nbframes & 0x0000ff00) >> 8); + buffer[5] = (unsigned char)(nbframes & 0x000000ff); + + for (int i = 0 ; i < nbangles ; i++) + { + buffer[6 + 2 * i] = (angles[i] & 0x0000ff00) >> 8; + buffer[6 + 2 * i + 1] = angles[i] & 0x000000ff; + } + _comport->WriteData(buffer, 6 + 2 * nbangles); + delete[] buffer; +} + void TactonPlayer::stopBuzz() { if (!_comport) diff --git a/TactonPlayer/TactonPlayer.hpp b/TactonPlayer/TactonPlayer.hpp index a5be777..c79e2ae 100644 --- a/TactonPlayer/TactonPlayer.hpp +++ b/TactonPlayer/TactonPlayer.hpp @@ -5,41 +5,51 @@ #define EXPORTED #else #include -#define EXPORTED __declspec(dllexport) + #ifdef _WINDLL + #define EXPORTED __declspec(dllexport) + #else + #define EXPORTED __declspec(dllimport) + #endif #endif -class TactonPlayer +class EXPORTED TactonPlayer { public: - EXPORTED TactonPlayer(const char *port = "COM5"); - EXPORTED ~TactonPlayer(); + TactonPlayer(const char *port = "COM5"); + ~TactonPlayer(); //set the timestamp to 0, and watch for scheduled tactons - EXPORTED void start(); + void start(); //stop watching scheduled tactons, and erase registered tactons - EXPORTED void stop(); + void stop(); //register a tacton - EXPORTED void regist(const Tacton &t); + void regist(const Tacton &t); //register a list of tactons in a file, returns the number of tactons loaded - EXPORTED unsigned int registFile(char *filename); + unsigned int registFile(char *filename); //play a registered tacton - EXPORTED void play(unsigned char index); + void play(unsigned char index); //play a specified tacton - EXPORTED void play(const Tacton &t); + void play(const Tacton &t); //schedule the play of a registered tacton - EXPORTED void schedule(unsigned char index, unsigned long timestamp); + void schedule(unsigned char index, unsigned long timestamp); //sets an amplitude for each vibrator - EXPORTED void setAmplitudes(unsigned char nbtactors, unsigned char *amplitudes); + void setAmplitudes(unsigned char nbtactors, unsigned char *amplitudes); //sets a frequency for all vibrator - EXPORTED void setFrequency(unsigned int frequency); + void setFrequency(unsigned int frequency); //stop any vibration - EXPORTED void stopBuzz(); + void stopBuzz(); + + //sets a vibration on a virtual circle around 4 vibrators + void playAngle(unsigned int angle); + + //plays an animation alterning a series of angles + void playAngleSequence(unsigned char nbangles, unsigned int frameduration, unsigned int nbframes, unsigned int *angles); //read on the serial port - EXPORTED void debugRead(char *res, int nb) const; + void debugRead(char *res, int nb) const; private: Serial *_comport; -- 2.30.2