{"id":624,"date":"2013-01-12T02:40:57","date_gmt":"2013-01-12T01:40:57","guid":{"rendered":"http:\/\/majek.mamy.to\/?p=624"},"modified":"2013-09-01T01:35:14","modified_gmt":"2013-08-31T23:35:14","slug":"rc-diy-transmitter","status":"publish","type":"post","link":"https:\/\/majek.sh\/en\/rc-diy-transmitter\/","title":{"rendered":"LCD88: R\/C DIY transmitter"},"content":{"rendered":"<p><\/p>\n<h1>Another one? \ud83d\ude42<\/h1>\n<p>There are some other open source transmitter projects, so why did I start another one?<br \/>\nAt first, I started it in 2009 &#8211; there wasn&#8217;t too much free options avaliable, ready made transmitters were also very expensive. And last, there weren&#8217;t enough flexible for me :-). Even right now I don&#8217;t know if similar transmitter exists, at least at affordable price, not thousands of $$ \ud83d\ude42<\/p>\n<p><a href=\"https:\/\/majek.sh\/happy-new-year-2013\/transmitter\/\" rel=\"attachment wp-att-607\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/transmitter-584x480.jpg\" alt=\"\" title=\"DYI transmitter\" width=\"584\" height=\"480\" class=\"alignnone size-medium wp-image-607\" srcset=\"https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/transmitter-584x480.jpg 584w, https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/transmitter-150x123.jpg 150w, https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/transmitter.jpg 1024w\" sizes=\"(max-width: 584px) 100vw, 584px\" \/><\/a><\/p>\n<h1>BLOCKS!<\/h1>\n<p>The gist of this project is: BLOCKS!<br \/>\nFor each model you have some sticks, pots, switches and output channels. Between inputs and outputs there is more or less flexible &#8216;black box&#8217;.<br \/>\nIn my project you could define exactly what is in this &#8216;black box&#8217; by connecting math blocks together in absolutely free way.<\/p>\n<p>Blocks could do:<\/p>\n<ul>\n<li>trims<\/li>\n<li>reverse<\/li>\n<li>add<\/li>\n<li>substract<\/li>\n<li>negate<\/li>\n<li>expo<\/li>\n<li>multiply<\/li>\n<li>convert any analog value to 3 state (for switch conditioning)<\/li>\n<li>some casual mixers<\/li>\n<li>limits<\/li>\n<li>and many more&#8230;<\/li>\n<\/ul>\n<p>Better explanation is just to show some examples, so look at them!<br \/>\nFor examples you should only know that channels 0-7 are inputs, 16-23 are outputs, some has special meaning or are reseved but right now it&#8217;s not important.<\/p>\n<h2>Simple model &#8211; as in all entry level transmitters<\/h2>\n<p>It&#8217;s easy:<br \/>\n<a href=\"https:\/\/majek.sh\/rc-diy-transmitter\/1-ch-simple\/\" rel=\"attachment wp-att-702\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/1-ch-simple.png\" alt=\"\" title=\"Simple 1 channel build from blocks.\" width=\"552\" height=\"222\" class=\"alignnone size-full wp-image-702\" srcset=\"https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/1-ch-simple.png 552w, https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/1-ch-simple-150x60.png 150w\" sizes=\"(max-width: 552px) 100vw, 552px\" \/><\/a><\/p>\n<p>Channel 0 (CH0) is stick input, value goes into <em>reverse<\/em> block. Another input for this block is CH40 which remebers reverse position. Output of <em>reverse<\/em> block goes to channel 52. Another stage is <em>trim<\/em> block which takes value from channel 52 and adds it to trim value from channel 28. Other channels should be done in similar way.<br \/>\nSpecial block <em>reverse<\/em> is in fact a <em>multiply<\/em> block but it&#8217;s treaten in special way &#8211; second channel connected to it shows automaticly in &#8216;Reverse&#8217; menu.<br \/>\nIn similar way <em>trim<\/em> block is an <em>add<\/em> block which second input shows in &#8216;Trims&#8217; menu.<\/p>\n<p>Looks easy, isn&#8217;t it? So, let&#8217;s go ahead.<\/p>\n<h2>Delta or flying wing<\/h2>\n<p>Another example: delta mixer.<br \/>\nAt the beggining let&#8217;s write some equations:<\/p>\n<div class=\"codecolorer-container text railscasts\" style=\"overflow:auto;white-space:nowrap;width:550px;\"><div class=\"text codecolorer\">left aileron = ( rudder stick + elevator stick ) \/2<br \/>\nright aileron = ( - rudder stick + elevator stick ) \/2<\/div><\/div>\n<p>So let&#8217;s draw blocks to calulate it:<br \/>\n<a href=\"https:\/\/majek.sh\/rc-diy-transmitter\/delta\/\" rel=\"attachment wp-att-704\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/delta.png\" alt=\"\" title=\"Delta mixer made using blocks\" width=\"551\" height=\"274\" class=\"alignnone size-full wp-image-704\" srcset=\"https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/delta.png 551w, https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/delta-150x74.png 150w\" sizes=\"(max-width: 551px) 100vw, 551px\" \/><\/a><\/p>\n<p>Ok, but this is only mixer, what about trims, reverses etc?<\/p>\n<p>So, look at real life model:<br \/>\n<a href=\"https:\/\/majek.sh\/rc-diy-transmitter\/delta-full\/\" rel=\"attachment wp-att-713\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/delta-full.png\" alt=\"\" title=\"Flying wing - model made using blocks\" width=\"550\" height=\"384\" class=\"alignnone size-full wp-image-713\" srcset=\"https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/delta-full.png 550w, https:\/\/majek.sh\/wp-content\/uploads\/2013\/01\/delta-full-150x104.png 150w\" sizes=\"(max-width: 550px) 100vw, 550px\" \/><\/a><br \/>\nLooks complicated, but let me explain what&#8217;s going on.<\/p>\n<p>A little transformed formula for delta mixer in this case:<\/p>\n<div class=\"codecolorer-container text railscasts\" style=\"overflow:auto;white-space:nowrap;width:550px;\"><div class=\"text codecolorer\">right aileron=0.5*elevator+0.5*rudder<br \/>\nleft aileron=0.5*elevator-0.5*rudder<\/div><\/div>\n<p>I think that most people who flies flying wing could confirm that this type of model is very sensitive to elevator moves. One solution for this is to make expo\/DR on elevator channel. But I preffer make elevator just less sensitive in favor to rudder. So, instead of using 0.5 coefficient to multiply values from both channels, I use smaller one for elevator and greater for rudder. If coeficcients sum up to 1, results will be still within allowed range (I already did it on my standalone delta mixer based on ATTINY13).<\/p>\n<p>Let&#8217;s look at above picture. Blocks 1-3 are here to make flexible coefficients. On Block1 input is 1 (CH25) and trim (CH40), so it makes at output (CH41) value in range 0&#8230;2 dependent on trim position. It&#8217;s too big to further calculations, so we must scale it down using Block2. At it&#8217;s output (CH43) we have value in range 0&#8230;1. Block3 calculate second coefficient for multiplication (CH44=1-CH43). Blocks 5,7,10,11,12, form a delta mixer with adjustable amplification for both control sticks. After delta mixer, there are reverse and trims blocks to adjust servo direction and neutral point. Near input there are blocks 4,6 and 8 &#8211; there are standard trims for fine tuning during fly.<\/p>\n<p>So, as long as you could make some equations to describe how channel values should be processed, you could make it.<\/p>\n<p>Enough about blocks:-) Let&#8217;t go to other topics.<\/p>\n<h1>Software architecture<\/h1>\n<p>There are few types of tasks inside transmitter:<\/p>\n<ul>\n<li>critical &#8211; generating accurate PPM<\/li>\n<li>high priority &#8211; get values from inputs, calculate blocks and store results for PPM<\/li>\n<li>best effort &#8211; user interface (menu, displaying something on LCD, trims, options etc.)<\/li>\n<\/ul>\n<h2>Generating PPM<\/h2>\n<p>I use hardware PWM generator to make an accurate PPM signal. In best possible way \ud83d\ude42<br \/>\nThat&#8217;s possible because of using timer in CTC mode and interrupts with right, but not so critical place in time. The point is that writing new value to timer in this mode during generating waveform is effective only for new cycle and doesn&#8217;t affect current operation, so it could be calculated and programmed anytime during this period. I calculate it just after end of synchro pulse (in interrupt triggered by this event), so CPU has at least 10000 clocks to do it, and this is more than enough. Because of that, there is absolutely no jitter and pulses are just perfect. \ud83d\ude42<\/p>\n<h2>Getting values, calculating it and other things<\/h2>\n<p>That&#8217;s another cool solution here: multitasking in AVR!<br \/>\nAfter copying output values to buffer for generating PPM, CPU starts getting analog values from ADCs (using interrupts). They are filtered and recalculated and results are put in input channels. Meantime 2 thing are running: PPM generation using interrups and user interface or other not critical things. When all values from inputs are ready, a task switch occurs. User interface thread is interrupted, state is saved to ram and block calculation task begins. After processing and calculating all blocks, this task ends and switches back to user interface task.<\/p>\n<p>This way PPM is generated perfectly, calculating blocks is done in high priority thread, and the rest fo time could be used to draw some fancy things on color LCD \ud83d\ude42<br \/>\nGreat advantage of multitasking is that during programming user interface I could do whatever I want without bothering myself about timing as long as interrupts are enabled.<\/p>\n<h2>Memory<\/h2>\n<p>I decided to use internal flash memory as main storage for model definitions (blocks, initial channel values etc.). I organized data into containers with headers containing information about model number, contents of container (block, channel, comment&#8230;) and length. And one important rule: there could be many containers with the same &#8216;id&#8217; but only last in memory is valid. It makes updates as simple as writing new version of container at the end of other containers. It also help to reduce flash write\/erase cycles. Only drawback is that memody should be compacted from time to time.<br \/>\nBut using trims could fill all flash memory very fast, so I decided to make temporary storage only for channels (4 bytes\/ch) in eeprom. In future there will be possibility to move values from eeprom back to flash. It will be needed to backup\/restore model definitions.<\/p>\n<h1>Features<\/h1>\n<ul>\n<li>Model memory (maximum 31).<\/li>\n<li>Each model comprise of:\n<ul>\n<li>comments, model name is one of them and is mandatory (maximum 256 per model) &#8211; they could be assigned to channels and blocks<\/li>\n<li>channels, some are dedicated to inputs, some to outputs, the rest could be used for trims, reverses, connections between blocks etc. (maximum 253 per model)<\/li>\n<li>blocks, they do math operations on input channels and store result to another channel(s) (maximum 255 per model)<\/li>\n<li>block processing order, right now you must manually generate list of blocks in order they should be processed<\/li>\n<\/ul>\n<\/li>\n<li>8 output channels, but it could be increased keeping in mind that output frame should be extended<\/li>\n<li>8 analog inputs, they can be also &#8216;conditioned&#8217; and used for switches<\/li>\n<li>PPM output (super accurate, jitter free, ~11000 steps per channel)<\/li>\n<li>internal calculations does on 16 bit fixed point numbers (6+10), it is equivalent of more than 2048 steps<\/li>\n<li>serial bootloader, so firmware upgrade could be done using standard usb-serial cable\/interface<\/li>\n<li>Colour LCD screen<\/li>\n<li>6 keys for menu navigation<\/li>\n<li>Open source! (code will be available soon)<\/li>\n<\/ul>\n<h1>A little bit of history<\/h1>\n<p>In 2006, when I started to think about R\/C models, I bought cheapest 4 channel transmitter with idea, that if I&#8217;ll need more &#8211; I&#8217;ll make it:-)<br \/>\nSomewhere between 2007 and 2008, during discussion on Alexrc forum, idea of very flexible and fully programmable transmitter were born.<br \/>\nIdea was to define model inside transmitter using basic blocks (sum, multiply etc) and connections between inputs, blocks and outputs.<br \/>\nIn 2008 I made a universal board for my projects using Atmega8L and LCD screen from Siemens S65 phone.<br \/>\nIn 2009 I replaced Atmega8L with Atmega88 &#8211; it allowed to safely (within cpu specs) increase cpu clock up to 11MHz while still running at 3V. And then real story begins:-)<br \/>\nAt the end of 2009 I had some things finished: generating ppm, calculating blocks and basics of user interface (menu, keyboard). And then project stuck for almost 3 years.<br \/>\nI tried to make it too universal, and it didn&#8217;t worked for UI. During these years I used simple transmitters &#8211; there were enough for my planes. But at the end <a href=\"https:\/\/majek.sh\/en\/tricopter\/\" title=\"Tricopter\">Tricopter<\/a> appeared:-) Problems with arming <a href=\"https:\/\/majek.sh\/en\/multiwii-328p-controller-from-hk\/\" title=\"MultiWii 328P controller from HK\">control board<\/a> and need for more channels resurrected old project.<br \/>\nSo, at the end od 2012 i removed some code (mostly UI related), revised some assumption (store model definitions not only in flash, but also use eeprom for this), and project moved forward.<br \/>\nI put this board into empty old transmitter bought at about $2, added <a href=\"http:\/\/www.hobbyking.com\/hobbyking\/store\/uh_viewitem.asp?idproduct=17205&#038;aff=78124\" target=\"_blank\">FrSky DHT module<\/a>, connected all together and right now it could be used in real world:-)<\/p>\n<h1>Future<\/h1>\n<ul>\n<li>Switch to Atmega168 or Atmega328 (I have both and code is ready &#8211; it&#8217;s only a matter of doing PCB and solder it together)<\/li>\n<li>Because right now there is almost impossible to buy S65 LCD display (but I have few \ud83d\ude42 ), I bought another similar one. Plan is to make code supporting also this new display.<\/li>\n<li>Change code to run on standard Arduino board based on Atmega328 (check all timings in code and rewrite it to support other cpu frequencies)<\/li>\n<li>More code, more features (but not on Atmega88 because I already hit memory limit)<\/li>\n<li>Timers, i\/o extender (more inputs, trainer mode)<\/li>\n<li>&#8230;<\/li>\n<\/ul>\n<p><\/p>","protected":false},"excerpt":{"rendered":"<p>Another one? \ud83d\ude42 There are some other open source transmitter projects, so why did I start another one? At first, I started it in 2009 &#8211; there wasn&#8217;t too much free options avaliable, ready made transmitters were also very expensive. <span class=\"excerpt-dots\">&hellip;<\/span> <a class=\"more-link\" href=\"https:\/\/majek.sh\/en\/rc-diy-transmitter\/\"><span class=\"more-msg\">Continue reading &rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,5],"tags":[38,50,24,26,41,40,13,39],"_links":{"self":[{"href":"https:\/\/majek.sh\/en\/wp-json\/wp\/v2\/posts\/624"}],"collection":[{"href":"https:\/\/majek.sh\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/majek.sh\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/majek.sh\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/majek.sh\/en\/wp-json\/wp\/v2\/comments?post=624"}],"version-history":[{"count":97,"href":"https:\/\/majek.sh\/en\/wp-json\/wp\/v2\/posts\/624\/revisions"}],"predecessor-version":[{"id":1156,"href":"https:\/\/majek.sh\/en\/wp-json\/wp\/v2\/posts\/624\/revisions\/1156"}],"wp:attachment":[{"href":"https:\/\/majek.sh\/en\/wp-json\/wp\/v2\/media?parent=624"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/majek.sh\/en\/wp-json\/wp\/v2\/categories?post=624"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/majek.sh\/en\/wp-json\/wp\/v2\/tags?post=624"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}