Advertisement
Guest User

Untitled

a guest
Jan 21st, 2019
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.75 KB | None | 0 0
  1. #include <ESP8266WiFi.h>
  2. #include <IRremoteESP8266.h>
  3. #include <IRsend.h>
  4.  
  5.  
  6. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  7. // Global definitions (should be moved to a header file)
  8. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. const int STATUS_PIN = 13;
  10.  
  11.  
  12. #define M_BIT_DURATION_IN_USEC (976-25) //Duration of a logical "1"
  13. #define S_BIT_DURATION_IN_USEC (976+30) //Duration of a logical "0"
  14. #define M_TOTAL_DURATION_CORRECTION (103) //Correction factor due to inaccuracies in generation
  15. #define S_TOTAL_DURATION_CORRECTION (-130) //Correction factor due to inaccuracies in generation
  16. #define BASE_TEMPERATURE (15)
  17.  
  18.  
  19. #define DATA_STREAM_SIZE (3+3+32*2+2*2)
  20. #define DURATION_ARRAY_SIZE (DATA_STREAM_SIZE*2+1)
  21. #define INPUT_ARRAY_SIZE (4)
  22. #define RAWBUF 100 // Length of raw duration buffer
  23.  
  24.  
  25. typedef enum {
  26. FAN_LOW = 0,
  27. FAN_MED,
  28. FAN_HIGH,
  29. FAN_AUTO,
  30. } fanSpeed_e;
  31.  
  32.  
  33. typedef enum {
  34. MODE_COOL = 1,
  35. MODE_HEAT,
  36. MODE_AUTO,
  37. MODE_DRY,
  38. MODE_FAN
  39. } mode_e;
  40.  
  41.  
  42. typedef enum {
  43. TX_OFF = 0,
  44. TX_ON
  45. } txMode_e;
  46.  
  47.  
  48. #pragma pack(push)
  49. #pragma pack(1)
  50. /////////////////////////////////////////////////////////
  51. // AC Status Control Word
  52. /////////////////////////////////////////////////////////
  53. typedef union{
  54. struct{
  55. uint32_t offMinutes :3; //Off timer control: tens of minutes to wait. Range: 0-5
  56. uint32_t offHours :5; //Off timer control: hours to wait. Range: 0-23
  57. uint32_t onMinutes :3; //On time control: tens of minutes to wait. Range: 0-5
  58. uint32_t onHours :5; //On time control: hours to wait. Range: 0-23
  59. uint32_t sleep :1; //Sleep mode. On(1)/off(0)
  60. uint32_t temprature :4; //Temperature. Range: 0(min)-15(max)
  61. uint32_t reserved1 :2; //Unused?
  62. uint32_t tilt :1; //Tilt control. On(1)/off(0)
  63. uint32_t tilt2 :1; //Tile2/Unused?
  64. uint32_t reserved0 :1; //Unused?
  65. uint32_t fanSpeed :2; //Fan speed. Min(0)/Med(1)/MAX(2)/AUTO(3)
  66. uint32_t mode :3; //Mode select. COOL(1)/HEAT(2)/AUTO(3)/DRY(4)/FAN(5)
  67. uint32_t power :1; //Toggle On/off. Toggle(1)/No change(0)
  68. };
  69. uint32_t rawVal;
  70. } acStatus_t;
  71.  
  72.  
  73. /////////////////////////////////////////////////////////
  74. // General program control
  75. /////////////////////////////////////////////////////////
  76. typedef struct{
  77. uint8_t tx; //Enable(1)/disable(0) IR transmission
  78. } progStatus_t;
  79. #pragma pack(pop)
  80.  
  81.  
  82.  
  83.  
  84. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  85. // Global variables
  86. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  87. IRsend irsend(4);
  88. acStatus_t acStatus={0,0,0,0,0,(28-BASE_TEMPERATURE),0,0,0,0,FAN_LOW, MODE_HEAT,0}; //Initialize default status
  89. progStatus_t progStatus={TX_ON};
  90.  
  91.  
  92. volatile boolean stringComplete = false; //Global flag for CMD parsing
  93. byte inputArray[INPUT_ARRAY_SIZE+1]={0}; //Buffer for CMD storage. Sets a trailing "0" to end strings
  94. uint8_t dataStream[DATA_STREAM_SIZE]={}; //Buffer for manchester code generation
  95. unsigned int rawCodes[DURATION_ARRAY_SIZE]; //Buffer for raw mark/space durations to be sent
  96. uint16_t rawCodes16[DURATION_ARRAY_SIZE];
  97.  
  98.  
  99.  
  100.  
  101. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  102. // Send the IR code
  103. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  104. void sendCode(uint32_t codeLen) {
  105. // Assume 38 KHz
  106. for (int i = 0; i < DURATION_ARRAY_SIZE; ++i)
  107. {
  108. rawCodes16[i] = rawCodes[i];
  109. }
  110. irsend.sendRaw(rawCodes16, codeLen, 38);
  111. }
  112.  
  113.  
  114.  
  115.  
  116. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  117. // Converts the AC Status DWORD to a '01/10' Manchester Code stream, adding the required prefix and suffix
  118. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  119. uint8_t statusToDataStream(uint8_t* dataStream, acStatus_t& acStatus){
  120. uint8_t bitBuffer[32];
  121. uint32_t value=acStatus.rawVal;
  122. for (uint8_t i=0;i<32;i++){
  123. uint32_t bitVal=((value&0x80000000)==0)?0:1;
  124. bitBuffer[i]=bitVal;
  125. value=(value<<1);
  126. }
  127.  
  128.  
  129. //Write prefix
  130. uint8_t idx=0;
  131. dataStream[idx++]=1;
  132. dataStream[idx++]=1;
  133. dataStream[idx++]=1;
  134. dataStream[idx++]=0;
  135. dataStream[idx++]=0;
  136. dataStream[idx++]=0;
  137. //Write actaul status
  138. for(uint8_t i=0;i<32;i++){
  139. uint8_t bitVal=bitBuffer[i];
  140. dataStream[idx++] = (bitVal==0)?1:0;
  141. dataStream[idx++] = (bitVal==0)?0:1;
  142. }
  143. //Write Suffix
  144. dataStream[idx++]=0;
  145. dataStream[idx++]=1;
  146. dataStream[idx++]=1;
  147. dataStream[idx++]=0;
  148.  
  149.  
  150. return(idx);
  151. }
  152.  
  153.  
  154.  
  155.  
  156. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  157. // Converts the the '01/10' Manchester Code data stream to a "Raw Durations Buffer", as required by IRSend
  158. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  159. uint8_t dataStreamToDurations(uint8_t* srcData, uint8_t len){
  160. //Assuming data stream begins with HIGH
  161. uint8_t smIdx=0;
  162. uint32_t duration=M_BIT_DURATION_IN_USEC;
  163. for (uint8_t streamIdx=1;streamIdx<len;streamIdx++){
  164. if (smIdx==RAWBUF){
  165. break;
  166. }
  167. if (srcData[streamIdx]==srcData[streamIdx-1]){ //No change, accumulate duration
  168. if (srcData[streamIdx]==1){
  169. duration+=M_BIT_DURATION_IN_USEC;
  170. }else{
  171. duration+=S_BIT_DURATION_IN_USEC;
  172. }
  173. }else{
  174. if (srcData[streamIdx]==1){ //Level changed, save total duration
  175. rawCodes[smIdx]=duration+M_TOTAL_DURATION_CORRECTION;
  176. duration=M_BIT_DURATION_IN_USEC;
  177. }else{
  178. rawCodes[smIdx]=duration+S_TOTAL_DURATION_CORRECTION;;
  179. duration=S_BIT_DURATION_IN_USEC;
  180. }
  181. smIdx++;
  182.  
  183. }
  184. if(smIdx>=DURATION_ARRAY_SIZE){
  185. Serial.print("Cannot create MARK/SPACE duration array"); //This should not happen
  186. return(smIdx);
  187. }
  188. }
  189. rawCodes[smIdx]=duration; //Save last duration
  190. return(smIdx+1);
  191. }
  192.  
  193.  
  194.  
  195.  
  196. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. // Dump a raw duration buffer to the serial port (for debug)
  198. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  199. void printCode(unsigned int * durationBuff, uint8_t len){
  200. for (int i = 0; i < len; i++) {
  201. if ((i % 2)==0) {
  202. // Mark
  203. Serial.print(" m");
  204. }else {
  205. // Space
  206. Serial.print(" s");
  207. }
  208. Serial.print(durationBuff[i], DEC);
  209. }
  210. Serial.println("");
  211. return;
  212. }
  213.  
  214.  
  215.  
  216.  
  217. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  218. // Dump the AC Status to the serial port
  219. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  220. void printStatus(){
  221. Serial.print("[P:");
  222. Serial.print(acStatus.power);
  223. Serial.print(" M:");
  224. Serial.print(acStatus.mode);
  225. Serial.print(" F:");
  226. Serial.print(acStatus.fanSpeed);
  227. Serial.print(" L:");
  228. Serial.print(acStatus.tilt2);
  229. Serial.print(" I:");
  230. Serial.print(acStatus.tilt);
  231. Serial.print(" T:");
  232. Serial.print(acStatus.temprature);
  233. Serial.print(" S:");
  234. Serial.print(acStatus.sleep);
  235. Serial.print(" oN:");
  236. Serial.print(acStatus.onHours);
  237. Serial.print(":");
  238. Serial.print(acStatus.onMinutes);
  239. Serial.print(" Off:");
  240. Serial.print(acStatus.offHours);
  241. Serial.print(":");
  242. Serial.print(acStatus.offMinutes);
  243. Serial.print("][0x");
  244. Serial.print(acStatus.rawVal,HEX);
  245. Serial.print("][tX:");
  246. Serial.print(progStatus.tx);
  247. Serial.println("]");
  248. }
  249.  
  250.  
  251.  
  252.  
  253. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  254. // Setup the serial communication, pin modes, etc.
  255. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  256. void setup()
  257. {
  258. Serial.begin(9600);
  259. pinMode(STATUS_PIN, OUTPUT);
  260. Serial.println("Runnning ac_rc");
  261. printStatus();
  262. irsend.begin();
  263. }
  264.  
  265.  
  266.  
  267.  
  268. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  269. // Main loop: Wait for CMD from serial port, then send IR code
  270. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  271. void loop() {
  272. serialEvent();
  273. /////////////////////////////////////////////////////////
  274. // Step 0: Parse CMD from serial port
  275. /////////////////////////////////////////////////////////
  276. if(stringComplete!=false){ //Wait for control word from serial port
  277. stringComplete = false;
  278.  
  279. uint8_t cmd=inputArray[0]; //Get control character
  280. uint8_t cmdVal=atoi((const char*)&inputArray[1]); //Get command value
  281. Serial.print("CMD:");
  282. Serial.println((char*)inputArray);
  283. acStatus.power=0; //The "Power" property is momentary, needs to be reset to avoid unintended on/off toggle
  284. switch(cmd){
  285. case 'P':
  286. acStatus.power=1;
  287. break;
  288. case 'M':
  289. acStatus.mode=cmdVal;
  290. break;
  291. case 'F':
  292. acStatus.fanSpeed=cmdVal;
  293. break;
  294. case 'L':
  295. acStatus.tilt2=cmdVal;
  296. break;
  297. case 'I':
  298. acStatus.tilt=cmdVal;
  299. break;
  300. case 'T':
  301. acStatus.temprature=cmdVal;
  302. break;
  303. case 'S':
  304. acStatus.sleep=cmdVal;
  305. break;
  306. case 'N':
  307. acStatus.onHours=cmdVal/6;
  308. acStatus.onMinutes=cmdVal%6;
  309. break;
  310. case 'O':
  311. acStatus.offHours=cmdVal/6;
  312. acStatus.offMinutes=cmdVal%6;
  313. break;
  314. case 'X':
  315. progStatus.tx=cmdVal;
  316. printStatus();
  317. return; //Don't continue
  318. break;
  319. case 'U':
  320. printStatus();
  321. return; //Don't continue
  322. break;
  323. default:
  324. Serial.println("Error decoding CMD!");
  325. return; //Don't continue past here...
  326. }
  327. printStatus();
  328.  
  329. /////////////////////////////////////////////////////////
  330. // Step 1: Create data stream from status
  331. /////////////////////////////////////////////////////////
  332. uint8_t dataLen=statusToDataStream(dataStream,acStatus); //Create a data stream from the status
  333. if (dataLen!=DATA_STREAM_SIZE){
  334. Serial.print("Error! Unexpected code length (");
  335. Serial.print(dataLen);
  336. Serial.println(")");
  337. return;
  338. }
  339. //At this point, dataLen=74
  340.  
  341. /////////////////////////////////////////////////////////
  342. // Step 2: Convert data stream to durations array
  343. /////////////////////////////////////////////////////////
  344. uint8_t len=dataStreamToDurations(dataStream,dataLen);
  345. //printCode(rawCodes,len); //Dump duration array to serial port
  346.  
  347.  
  348. /////////////////////////////////////////////////////////
  349. // Step 3: Send the IR code.
  350. // Data is transmitted six times:
  351. // {data,data,data,BREAK,data,data,data}
  352. /////////////////////////////////////////////////////////
  353.  
  354. if (progStatus.tx!=0){
  355. Serial.print("Sending code...");
  356. digitalWrite(STATUS_PIN, HIGH);
  357. //Send data 3 times
  358. for (uint8_t i=0;i<3;i++){ //Data needs to be send 3 times
  359. sendCode(len);
  360. }
  361. //Send BREAK
  362. irsend.mark(4*M_BIT_DURATION_IN_USEC+M_TOTAL_DURATION_CORRECTION);
  363. irsend.space(33370);
  364. //Send data 3 times more
  365. for (uint8_t i=0;i<3;i++){
  366. sendCode(len);
  367. }
  368. digitalWrite(STATUS_PIN, LOW);
  369. Serial.println("Done!");
  370. }
  371. Serial.println("");
  372. }//stringComplete
  373. }
  374.  
  375.  
  376.  
  377.  
  378. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  379. // Process incoming serial communication.
  380. // Flag "complete" when end of string isdetected.
  381. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  382. void serialEvent(){
  383. static byte inputPos=0;
  384. while (Serial.available()) {
  385. // get the new byte:
  386. char inChar = (char)Serial.read();
  387. inputArray[inputPos]=inChar;
  388. inputPos=(inputPos+1)%INPUT_ARRAY_SIZE;
  389. // if the incoming character is a newline or a carriage return, set a flag
  390. // so the main loop can do something about it:
  391. if (inChar == '\n' || inChar == '\r' ||inChar == 0) {
  392. inputPos=0;
  393. stringComplete=1;
  394. }else{
  395. stringComplete=0;
  396. }
  397. }
  398. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement