Hello! This is a tutorial to produce a text-composition device using an Arduino with text storage and return capabilities to the serial console. In its current form it is not particularly useful, and is more of an entertaining exercise, but the hardware setup and code may be expanded upon or incorporated into other projects as a relatively cheap way to compose text. With the addition of a GSM or 3G shield, and minor code changes and additions, this setup could actually be used as a simple text-sending phone.

Here is a video demo of most of the functionality, including text entry, line wrapping, screen-clearing, spaces, backspaces, serial output, and the end of composition menu, featuring the re-display of stored text upon backspacing, as well as the capability to output a final message and clear the display and storage.

You will need:
An Arduino (I used an Uno R3)
A 16x2 LCD (with or without backlight, your choice. Different sizes could be used with accommodations made in the code)
A breadboard, male-male and male-female jumpers (depends on how permanent this will be, and what headers are where)
5x 2k ohm resistors
1x 240 ohm resistor

The resistor values are not nessisarily set in stone, the 2k ones could most likely be subbed with anything 1k-5k, and the 240 could be anything 100-500, but I make no guarantees that those will cooperate (they probably will though). One of the 2k's and the 240 are used for creating a voltage divider for the contrast on the LCD. Normally this is accomplished with a potentiometer, so substitute as you feel fit.

Step 1: Hardware Setup

The diagram should explain the majority of the hardware setup, which is essentially an expansion of your typical basic LCD setup. Data output lines, however, are shared between the LCD and the keypad. These outputs go to the rows on the keypad in order to normally write them high. If any press occurs, it is detected by one of the columns going high, as the columns are hooked up to be inputs. A high signal as then cycled through the rows and then the keypress is located based on which column goes high when which row is high. Afterwards all rows are returned to the initial high state. After any commands to the LCD, all rows are written high again to ensure that no odd behavior occurs on the LCD, and keypress detection still functions. The resistors on the right of the diagram are the 2k ohm pulldowns for the column inputs to the Arduino, and the resistors on the left for the voltage divider that (as I mentioned earlier) can be replaced with a potentiometer if one wishes to do so.

Step 2: Code

I've attempted to comment this code extensively, but if anything in it remains unclear, please do ask! I've attached the .ino file to make uploading the code simple.

Note: I wrote this code before I had a handle on Object-Oriented Programming, and so the structure and organization of the code could certainly be better, but it still does function perfectly. I would update the code, but I no longer have the hardware on-hand and so would not be able to test it sufficiently. It is my hope, however, that the lack of OOP will make the code simpler to follow for Arduino beginners.

Step 3: Finished!

I hope that you found all this useful! If you have any questions feel free to ask. Thanks!
<p>hello, I use this code to my project sms text<br>messaging with gsm900d and I add some<br>code my project need to input the NUMBER<br>&amp; MESSAGE , when I input the<br>number alone i can receive a message but <br>when i input the number and message I can&rsquo;t receive any message.. how can fix this please help me . here&rsquo;s the code I add.</p><p>#include<br>&lt;LiquidCrystal.h&gt; //include the<br>lcd library</p><p>#include &lt;String.h&gt;</p><p>#include &lt;Keypad.h&gt;</p><p>#include<br>&lt;SoftwareSerial.h&gt;</p><p>#include<br>&quot;SIM900.h&quot;</p><p>#include &quot;sms.h&quot;</p><p>SMSGSM sms;</p><p>const byte row1=3; //keypad row pins, shared with the lcd<br>data lines</p><p>const byte row2=4;</p><p>const byte row3=5;</p><p>const byte row4=6;</p><p>const byte col1=7; //keypad column lines</p><p>const byte col2=8;</p><p>const byte col3=9;</p><p>const byte col4=10;</p><p>LiquidCrystal lcd(12, 11,<br>row4, row3, row2, row1); //lcd object</p><p>byte numpressed; //latest<br>number pressed on the keypad</p><p>byte timespressed; //times<br>the number has been pressed</p><p>byte cursorx=0; //cursor x<br>position</p><p>byte cursory=0; //cursor y<br>position</p><p>byte lastnumpressed; //the<br>initial number pressed on the keypad</p><p>char letter; //stores<br>letter that needs to be printed to the lcd</p><p>char typedtext[140];<br>//stores typed text for printout to the serial console</p><p>char phoneNumber [12];</p><p>const int wait=1000;<br>//time to wait for additional presses to same number</p><p>const int<br>preventholddelay=150; //time to wait to prevent cycling through things too<br>quickly</p><p>unsigned long basetime;<br>//base time for while loop</p><p>unsigned long elapsed=0;<br>//elapsed time in while loop</p><p>bool<br>disablespacedelay=false; //disables the delay in the space function in the case<br>that a different number is pressed while in while loop</p><p>bool promptkeypress=false;<br>//used for waiting for, and keypress detection, at the end-of composition<br>prompt</p><p>const byte<br>maxtimespressed[16]={</p><p> 1,3,4,4,4,4,4,4,4,4,1,7,1,1,1,1}; //stores<br>maximum number of times any given key can be pressed before looping back to its<br>first letter (used by incrementtimespressed function)</p><p>int positionintypedtext=0;<br>//position in typedtext character array</p><p>int charremaining;<br>//remaining characters in message</p><p>int<br>positioninphoneNumber=0;</p><p>void setup(){</p><p>//KEYPAD </p><p> Serial.begin(9600); //initiate gizduino witha baud<br>rate of 9600</p><p> lcd.begin(20,4); //initialize the lcd</p><p> lcd.setCursor(cursorx,cursory); //set the lcd<br>cursor</p><p> lcd.noCursor(); //turn off the cursor</p><p> pinMode(row1,OUTPUT); //set the rows as<br>outputs</p><p> pinMode(row2,OUTPUT);</p><p> pinMode(row3,OUTPUT);</p><p> pinMode(row4,OUTPUT);</p><p> pinMode(col1,INPUT); //set the columns as inputs</p><p> pinMode(col2,INPUT);</p><p> pinMode(col3,INPUT);</p><p> pinMode(col4,INPUT);</p><p> delay(wait);</p><p> lcd.cursor(); //turn the cursor on again<br>after a delay equivalent to wait</p><p> rowshigh(); //sets all rows high</p><p> mainMenu();</p><p>}</p><p>void loop(){</p><p> numpressed=16; //reset<br>&quot;numpressed&quot; (16 doesn't refer to any button on the pad)</p><p> if (findpress()){ //look for presses, if one<br>has occurred, identify it and continue</p><p> timespressed=0; //reset<br>&quot;timespressed&quot;</p><p> if (numpressed==0){ //if zero on the pad<br>was pressed,</p><p> dozero(); //print zero</p><p> letter='0'; //manually seed a zero as the<br>character for the text storage</p><p> textstorage(1); //regular character<br>storage</p><p> }</p><p> if (numpressed==10){ //if shift on the pad<br>was pressed,</p><p> textstorage(2); //perform a space in<br>storage</p><p> dospace(); //do a space</p><p> }</p><p> if (numpressed==14){ //if the arrows on the<br>pad were pressed,</p><p> textstorage(3); //perform a backspace in<br>storage</p><p> dobackspace(); //do a backspace</p><p> }</p><p> if (numpressed==15){ //if enter on the pad<br>was pressed,</p><p> if (gsm.begin(9600)) //condition if gsm is initialized</p><p> <br>Serial.println(&quot;\nstatus=READY&quot;); //displays &quot;ready&quot; on the serial<br>monitor if gsm is ready</p><p> else<br>Serial.println(&quot;\nstatus=IDLE&quot;); //otherwise displays<br>&quot;idle&quot; on the serial monitor if gsm is not found </p><p> delay(1000);</p><p> sendTextMessage();</p><p> lcd.setCursor(3,3);</p><p> lcd.print(&quot;Sending..&quot;); </p><p> lcd.clear();</p><p> delay(1000);</p><p> mainMenu();</p><p> outputserial(); //output message and<br>display remaining characters to serial console</p><p> }</p><p> if<br>((numpressed&lt;10&amp;&amp;numpressed&gt;0)||numpressed==11){ //if<br>1,2,3,4,5,6,7,8,9, or 11 was pressed (any one of the keys with multiple<br>characters assigned),</p><p> lastnumpressed=numpressed; //record which<br>number was pressed,</p><p> basetime=millis(); //and take a base time<br>for the while loop</p><p> while (elapsed&lt;wait){ //while below<br>the time to wait,</p><p> if(findpress()){ //look for presses, if<br>one has occurred, identify it and continue</p><p> if (numpressed==lastnumpressed){ //if<br>it was the same as before,</p><p> incrementtimespressed();<br>//increment &quot;timespressed&quot;</p><p> <br>basetime=basetime+(wait-(wait-elapsed)); //roll up the base time, to<br>allow another wait period until next press of the same button</p><p> definepress(); //use<br>&quot;numpressed&quot; and &quot;timespressed&quot; to define<br>&quot;letter&quot;</p><p> lcd.print(letter); //print the<br>letter that was defined</p><p> lcd.setCursor(cursorx,cursory);<br>//maintain cursor position</p><p> rowshigh(); //return all rows high</p><p> delay(preventholddelay); //delay a<br>little to prevent continuous cycling through &quot;timespressed&quot; during a<br>single press</p><p> }</p><p> else{ //if the number that was pressed<br>was different than before,</p><p> disablespacedelay=true; //disable<br>the delay in the space function to allow the press to be detected a second<br>time, at the beginning of void loop</p><p> break; //break out of the while<br>loop</p><p> }</p><p> }</p><p> elapsed=millis()-basetime; //refresh<br>the elapsed time for the while loop</p><p> }</p><p> elapsed=0; //reset the elapsed time for<br>the while loop</p><p> textstorage(1); //store character</p><p> dospace(); //do a space</p><p> }</p><p> }</p><p> if (positionintypedtext==139){ //if the end<br>of the stored text has been reached,</p><p> promptkeypress=false; //reset keypress<br>detection</p><p> cursorx=0; //set cursor to the beginning of<br>first row</p><p> cursory=0;</p><p> lcd.setCursor(cursorx,cursory);</p><p> lcd.print(&quot;Msg end.<br>&lt;&gt;=back&quot;); //print this out to the lcd</p><p> cursorx=0; //set cursor to the beginning of<br>second row</p><p> cursory=1;</p><p> lcd.setCursor(cursorx,cursory);</p><p> lcd.print(&quot;enter=serial out&quot;);<br>//print this out to the lcd</p><p> rowshigh(); //sets all rows high</p><p> numpressed=16; //reset<br>&quot;numpressed&quot; (16 doesn't refer to any button on the pad)</p><p> while(!promptkeypress){ //while no relevant<br>keypresses have occurred, </p><p> if (findpress()){ //look for presses, if<br>one has occurred, identify it and continue</p><p> timespressed=0; //reset<br>&quot;timespressed&quot;</p><p> if (numpressed==14){ //if the arrows on<br>the pad were pressed,</p><p> promptkeypress=true; //take note so<br>that the while loop can be broken</p><p> textstorage(3); //perform a backspace<br>in storage</p><p> for (int i=0;i&lt;16;i++){ //print<br>out to the first line on the lcd from the stored text</p><p> cursorx=i;</p><p> cursory=0;</p><p> lcd.setCursor(cursorx,cursory);</p><p> lcd.print(typedtext[108+i]);</p><p> }</p><p> for (int j=0;j&lt;16;j++){ //print out to<br>the second line on the lcd from the stored text</p><p> cursorx=j;</p><p> cursory=1;</p><p> lcd.setCursor(cursorx,cursory);</p><p> lcd.print(typedtext[123+j]);</p><p> }</p><p> cursorx=15; //set cursor to the<br>beginning of second row</p><p> cursory=1;</p><p> lcd.setCursor(cursorx,cursory);</p><p> rowshigh(); //sets all rows high</p><p> }</p><p> if (numpressed==15){ //if enter on the<br>pad was pressed,</p><p> promptkeypress=true; //take note so<br>that the while loop can be broken</p><p> Serial.print(&quot;Final message:<br>&quot;); //print this to the serial console</p><p> Serial.println(typedtext); //print<br>out all the text typed so far to the serial console</p><p> <br>Serial.println(); //print a blank line</p><p> for (int i=0;i&lt;140;i++){ //write<br>all positions in the stored text to be blank</p><p> typedtext[i]=' ';</p><p> }</p><p> positionintypedtext=0; //reset the<br>position in the stored text to the beginning</p><p> doclear();</p><p> rowshigh(); //sets all rows high</p><p> }</p><p> }</p><p> }</p><p> delay(preventholddelay); //delay a little<br>to prevent continuous cycling</p><p> }</p><p>}</p><p>void rowshigh(){ //sets<br>all rows high</p><p> digitalWrite(row1,HIGH); //write all the rows<br>high</p><p> digitalWrite(row2,HIGH); </p><p> digitalWrite(row3,HIGH);</p><p> digitalWrite(row4,HIGH);</p><p>}</p><p>bool findpress(){ //finds<br>a press to define &quot;numpressed&quot;, if any press occurs, returns true</p><p> bool pressfound=false; //variable for any<br>press detection, is returned by this function</p><p> digitalWrite(row1,LOW); //write all rows low</p><p> digitalWrite(row2,LOW);</p><p> digitalWrite(row3,LOW);</p><p> digitalWrite(row4,LOW);</p><p> digitalWrite(row1,HIGH); //write first row<br>high</p><p> if (digitalRead(col1)==HIGH){ //if the first<br>column is now high, &quot;1&quot; has been pressed</p><p> numpressed = 1;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col2)==HIGH){ //if the second<br>column is now high, &quot;2&quot; has been pressed</p><p> numpressed = 2;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col3)==HIGH){ //if the third<br>column is now high, &quot;3&quot; has been pressed</p><p> numpressed = 3;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col4)==HIGH){ //if the fourth<br>column is now high, &quot;reset&quot; has been pressed</p><p> numpressed = 12;</p><p> pressfound=true;</p><p> }</p><p> digitalWrite(row1,LOW); //return first row<br>low</p><p> digitalWrite(row2,HIGH); //write second row<br>high</p><p> if (digitalRead(col1)==HIGH){ //if the first<br>column is now high, &quot;4&quot; has been pressed</p><p> numpressed = 4;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col2)==HIGH){ //if the second<br>column is now high, &quot;5&quot; has been pressed</p><p> numpressed = 5;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col3)==HIGH){ //if the third<br>column is now high, &quot;6&quot; has been pressed</p><p> numpressed = 6;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col4)==HIGH){ //if the fourth<br>column is now high, &quot;dial&quot; has been pressed</p><p> numpressed = 13;</p><p> pressfound=true;</p><p> }</p><p> digitalWrite(row2,LOW); //return second row<br>low</p><p> digitalWrite(row3,HIGH); //write third row<br>high</p><p> if (digitalRead(col1)==HIGH){ //if the first<br>column is now high, &quot;7&quot; has been pressed</p><p> numpressed = 7;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col2)==HIGH){ //if the second<br>column is now high, &quot;8&quot; has been pressed</p><p> numpressed = 8;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col3)==HIGH){ //if the third<br>column is now high, &quot;9&quot; has been pressed</p><p> numpressed = 9;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col4)==HIGH){ //if the fourth<br>column is now high, the arrows have been pressed</p><p> numpressed = 14;</p><p> pressfound=true;</p><p> }</p><p> digitalWrite(row3,LOW); //return third row<br>low</p><p> digitalWrite(row4,HIGH); //write fourth row<br>high</p><p> if (digitalRead(col1)==HIGH){ //if the first<br>column is now high, &quot;shift&quot; has been pressed</p><p> numpressed = 10;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col2)==HIGH){ //if the second<br>column is now high, &quot;0&quot; has been pressed</p><p> numpressed = 0;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col3)==HIGH){ //if the third<br>column is now high, &quot;.&quot; has been pressed</p><p> numpressed = 11;</p><p> pressfound=true;</p><p> }</p><p> if (digitalRead(col4)==HIGH){ //if the fourth<br>column is now high, &quot;enter&quot; has been pressed</p><p> numpressed = 15;</p><p> pressfound=true;</p><p> }</p><p> digitalWrite(row4,LOW); //return fourth row<br>low</p><p> rowshigh(); //write all rows high</p><p> return pressfound; //function returns true<br>if any press found, otherwise returns false</p><p>}</p><p>void definepress(){ //uses<br>&quot;lastnumpressed&quot; and &quot;timespressed&quot; to define<br>&quot;letter&quot;</p><p> if (lastnumpressed==1){</p><p> if (timespressed==1){</p><p> letter='1';</p><p> }</p><p> if (timespressed==2){</p><p> letter='Q';</p><p> }</p><p> if (timespressed==3){</p><p> letter='Z';</p><p> }</p><p> }</p><p> if (lastnumpressed==2){</p><p> if (timespressed==1){</p><p> letter='2';</p><p> }</p><p> if (timespressed==2){</p><p> letter='A';</p><p> }</p><p> if (timespressed==3){</p><p> letter='B';</p><p> }</p><p> if (timespressed==4){</p><p> letter='C';</p><p> }</p><p> }</p><p> if (lastnumpressed==3){</p><p> if (timespressed==1){</p><p> letter='3';</p><p> }</p><p> if (timespressed==2){</p><p> letter='D';</p><p> }</p><p> if (timespressed==3){</p><p> letter='E';</p><p> }</p><p> if (timespressed==4){</p><p> letter='F';</p><p> }</p><p> }</p><p> if (lastnumpressed==4){</p><p> if (timespressed==1){</p><p> letter='4';</p><p> }</p><p> if (timespressed==2){</p><p> letter='G';</p><p> }</p><p> if (timespressed==3){</p><p> letter='H';</p><p> }</p><p> if (timespressed==4){</p><p> letter='I';</p><p> }</p><p> }</p><p> if (lastnumpressed==5){</p><p> if (timespressed==1){</p><p> letter='5';</p><p> }</p><p> if (timespressed==2){</p><p> letter='J';</p><p> }</p><p> if (timespressed==3){</p><p> letter='K';</p><p> }</p><p> if (timespressed==4){</p><p> letter='L';</p><p> }</p><p> }</p><p> if (lastnumpressed==6){</p><p> if (timespressed==1){</p><p> letter='6';</p><p> }</p><p> if<br>(timespressed==2){</p><p> letter='M';</p><p> }</p><p> if (timespressed==3){</p><p> letter='N';</p><p> }</p><p> if (timespressed==4){</p><p> letter='O';</p><p> }</p><p> }</p><p> if (lastnumpressed==7){</p><p> if (timespressed==1){</p><p> letter='7';</p><p> }</p><p> if (timespressed==2){</p><p> letter='P';</p><p> }</p><p> if (timespressed==3){</p><p> letter='R';</p><p> }</p><p> if (timespressed==4){</p><p> letter='S';</p><p> }</p><p> }</p><p> if (lastnumpressed==8){</p><p> if (timespressed==1){</p><p> letter='8';</p><p> }</p><p> if (timespressed==2){</p><p> letter='T';</p><p> }</p><p> if<br>(timespressed==3){</p><p> letter='U';</p><p> }</p><p> if (timespressed==4){</p><p> letter='V';</p><p> }</p><p> }</p><p> if (lastnumpressed==9){</p><p> if (timespressed==1){</p><p> letter='9';</p><p> }</p><p> if (timespressed==2){</p><p> letter='W';</p><p> }</p><p> if (timespressed==3){</p><p> letter='X';</p><p> }</p><p> if (timespressed==4){</p><p> letter='Y';</p><p> }</p><p> }</p><p> if (lastnumpressed==11){</p><p> if (timespressed==1){</p><p> letter='.';</p><p> }</p><p> if (timespressed==2){</p><p> letter='?';</p><p> }</p><p> if (timespressed==3){</p><p> letter='!';</p><p> }</p><p> if<br>(timespressed==4){</p><p> letter=',';</p><p> }</p><p> if (timespressed==5){</p><p> letter='\'';</p><p> }</p><p> if (timespressed==6){</p><p> letter='&quot;';</p><p> }</p><p> if (timespressed==7){</p><p> letter='-';</p><p> }</p><p> }</p><p>}</p><p>void<br>incrementtimespressed(){ //increment &quot;timespressed&quot; until at max<br>value stored in maxtimespressed for that lastnumpressed, then roll over to 1</p><p> if<br>(timespressed==maxtimespressed[lastnumpressed]){ //if at the maximum,</p><p> timespressed=1; //roll over timespressed to<br>one</p><p> }</p><p> else{ //otherwise,</p><p> timespressed++; //increment timespressed</p><p> }</p><p>}</p><p>void dozero(){ //prints<br>zero</p><p> lcd.print('0'); //print 0</p><p> lcd.setCursor(cursorx,cursory); //maintain<br>cursor position</p><p> dospace(); //space</p><p>}</p><p>void dospace(){ //moves<br>cursor forward once, wraps to next line if necessary, clears and returns to top<br>of display if at bottom</p><p> if (cursory==1){ //if on the bottom row,</p><p> if (cursorx==14){ //if at the end of the<br>row,</p><p> cursorx=0; //define new cursor position as<br>the upper-left corner</p><p> cursory=0;</p><p> lcd.clear(); </p><p> }</p><p> else{ //otherwise,</p><p> cursorx++; //increment the cursor to the<br>right </p><p> }</p><p> }</p><p> else{ //if on the top row,</p><p> if (cursorx==19){ //if at the end of the<br>row,</p><p> cursorx=0; //define new cursor position<br>as the bottom-left corner</p><p> cursory=1;</p><p> }</p><p> else{ //otherwise,</p><p> cursorx++; //increment the cursor to the<br>right</p><p> }</p><p> }</p><p> lcd.setCursor(cursorx,cursory); //set cursor<br>to defined location</p><p> rowshigh(); //sets all rows high</p><p> if (disablespacedelay){ //if the delay has<br>been disabled,</p><p> disablespacedelay=false; //reset its being<br>disabled</p><p> }</p><p> else{ //otherwise,</p><p> delay(preventholddelay); //delay a bit</p><p> }</p><p>}</p><p>void doclear(){ //clears and<br>returns to top-left of display</p><p> cursorx=0;</p><p> cursory=0;</p><p> lcd.clear();</p><p> lcd.setCursor(cursorx,cursory);</p><p> rowshigh(); //sets all rows high</p><p> delay(preventholddelay);</p><p>}</p><p>void dobackspace(){ //does<br>a backspace, essentially the opposite of dospace</p><p> if (cursory==1){</p><p> if (cursorx==0){</p><p> cursorx=16;</p><p> cursory=0;</p><p> }</p><p> else{</p><p> cursorx--;</p><p> }</p><p> }</p><p> else{</p><p> if (cursorx==0){</p><p> cursorx=0;</p><p> cursory=0;</p><p> }</p><p> else{</p><p> cursorx--;</p><p> }</p><p> }</p><p> lcd.setCursor(cursorx,cursory);</p><p> lcd.print(&quot; &quot;);</p><p> lcd.setCursor(cursorx,cursory);</p><p> rowshigh(); //sets all rows high</p><p> delay(preventholddelay);</p><p>}</p><p>void textstorage(byte<br>mode){ //contains functions for text storage</p><p> if (mode==1){ //regular character storage</p><p> <br>phoneNumber[positioninphoneNumber]=letter; </p><p> positioninphoneNumber++;</p><p> // typedtext[positionintypedtext]=letter;<br>//store letter that was printed to LCD in typedtext</p><p> // <br>positionintypedtext++; //increment position in typedtext</p><p> }</p><p> if<br>(mode==2){ //do a space in stored text</p><p> //typedtext[positionintypedtext]=' '; //set<br>current position in typedtext to a space</p><p> //positionintypedtext++; //increment<br>position in typedtext</p><p> phoneNumber[positioninphoneNumber]=' ';</p><p> positioninphoneNumber++;</p><p> }</p><p> if (mode==3){ //does a backspace in the<br>stored text</p><p> //positionintypedtext--; //decrement<br>position in typedtext</p><p> //typedtext[positionintypedtext]=' '; //set<br>current position in typedtext to a space</p><p> positioninphoneNumber--;</p><p> phoneNumber[positioninphoneNumber]=' ';</p><p> } </p><p>} </p><p> void outputserial(){ //output message and<br>display remaining characters to serial console <br></p><p> Serial.print(&quot;Phonenumber: &quot;);</p><p> Serial.println(phoneNumber);</p><p> Serial.println(&quot;Message: &quot;);</p><p> Serial.print(typedtext); //print out all the<br>text typed so far to the serial console</p><p> // charremaining=(139-(positionintypedtext));<br>//calculate remaining characters</p><p> Serial.print(charremaining); //display<br>remaining characters</p><p> if (charremaining==1){ //making sure that the<br>plural is only used correctly</p><p> Serial.println(&quot; character<br>remaining&quot;);</p><p> }</p><p> else{</p><p> Serial.println(&quot; characters<br>remaining&quot;);</p><p> }</p><p> Serial.println(); //print a blank line</p><p> delay(preventholddelay); //delay a little to<br>prevent continuous cycling</p><p>}</p><p>void mainMenu(){ </p><p> lcd.clear(); </p><p> lcd.setCursor(0,0);</p><p> lcd.print(&quot;To:&quot;);</p><p> cursorx=3;</p><p> cursory=0;</p><p> lcd.setCursor(0,1);</p><p> lcd.print(&quot;Text:&quot;);</p><p> lcd.setCursor(0,1);</p><p> lcd.setCursor(cursorx,cursory);</p><p>}</p><p>void sendTextMessage()</p><p>{</p><p> sms.SendSMS(phoneNumber,typedtext); </p><p> delay(100);</p><p> Serial.println(&quot;\nSMS sent OK&quot;); </p><p> }</p>
<p>if i may ask why didnt you use the keypad.h i am trying to build something and i need to do the same thing to get the users email and address and i am using the keypad.h is it doable?</p>
<p>I didn't use keypad.h as it obfuscates the use of the keypad, and frankly it's really easy to manually implement, as I did here (basically writing a row high, checking for a high signal on each of the columns (corresponding with a button press), and then writing the next row high, etc.). One major advantage of manual implementation is that it allowed me to share digital pins between the keypad and the LCD. So it's up to you which way to go, the code I developed for this project is dependent on the manual keypad implementation that I did, so if you would like to build off of my code, using keypad.h likely won't work out easily. You should be able to easily change the letters and such in the code as necessary to adjust my code to match your keypad.</p>
<p>well first of all weldone for the tutorial.</p><p>i've made it and it was actualy very easy.</p><p>i have a problem conbining another code ( morse code encoder decoder ) to this .ino file.</p><p>this is the libraries : </p><p><a href="https://code.google.com/p/morse-endecoder/downloads/list" rel="nofollow">https://code.google.com/p/morse-endecoder/download...</a></p><p>and this is the code : </p><p>#include &lt;avr/pgmspace.h&gt;</p><p>#include &lt;MorseEnDecoder.h&gt;</p><p>// Pin mappings</p><p>const byte morseInPin = 7; </p><p>const byte morseOutPin = 13;</p><p>// Instantiate Morse objects</p><p>morseDecoder morseInput(morseInPin, MORSE_KEYER, MORSE_ACTIVE_LOW);</p><p>morseEncoder morseOutput(morseOutPin);</p><p>// Variables dealing with formatting the output somewhat</p><p>// by inserting CR's (carriage returns)</p><p>long lastTransmissionTime;</p><p>long currentTime;</p><p>boolean transmissionEnded = true; // Flag to mark old transmission is finished</p><p>// Minimum transmission pause time to insert carriage returns (CR)</p><p>// Adjust depending on Morse speed. IE 13 wpm = 646 ms between words (no CR).</p><p>const long transmissionPaused = 1000; // Suitable for 13 wpm?</p><p>void setup()</p><p>{</p><p> Serial.begin(9600);</p><p> Serial.println(&quot;Morse EnDecoder demo&quot;);</p><p> // Setting Morse speed in wpm - words per minute</p><p> // If not set, 13 wpm is default anyway</p><p> morseInput.setspeed(13);</p><p> morseOutput.setspeed(13);</p><p> lastTransmissionTime = (long)millis();</p><p>}</p><p>void loop()</p><p>{</p><p> currentTime = (long)millis();</p><p> // Needs to call these once per loop</p><p> morseInput.decode();</p><p> morseOutput.encode();</p><p> // SEND MORSE (OUTPUT)</p><p> // Encode and send text received from the serial port (serial monitor)</p><p> if (Serial.available() &amp;&amp; morseOutput.available())</p><p> {</p><p> // Get character from serial and send as Morse code</p><p> char sendMorse = Serial.read();</p><p> morseOutput.write(sendMorse);</p><p> // Not strictly needed, but used to get morseSignalString before it is destroyed</p><p> // (E.g. for morse training purposes)</p><p> morseOutput.encode();</p><p> // Also write sent character + Morse code to serial port/monitor</p><p> Serial.write(' ');</p><p> Serial.write(sendMorse);</p><p> Serial.write(morseOutput.morseSignalString);</p><p> }</p><p> // RECEIVE MORSE (INPUT)</p><p> // If a character is decoded from the input, write it to serial port</p><p> if (morseInput.available())</p><p> {</p><p> // Get decoded Morse code character and write it to serial port/monitor</p><p> char receivedMorse = morseInput.read();</p><p> Serial.print(receivedMorse);</p><p> // A little error checking </p><p> if (receivedMorse == '#') Serial.println(&quot;&lt; ERROR:too many morse signals! &gt;&quot;);</p><p> }</p><p> // Local Morse code feedback from input if not sending Morse simultaneously</p><p> if (morseOutput.available()) digitalWrite(morseOutPin, morseInput.morseSignalState);</p><p> // Check if ongoing transmission (not yet transmission pause)</p><p> if (!morseOutput.available() || morseInput.morseSignalState == true)</p><p> {</p><p> // reset last transmission timer and flag</p><p> lastTransmissionTime = currentTime;</p><p> transmissionEnded = false;</p><p> }</p><p> // Format output with carriage returns after a transmission pause</p><p> if ((currentTime - lastTransmissionTime) &gt; transmissionPaused)</p><p> {</p><p> if (transmissionEnded == false)</p><p> {</p><p> // Separate the transmissions somewhat in the serial monitor with CR's</p><p> for (int cr=0; cr&lt;2; cr++) Serial.println(&quot;&quot;); // some carriage returns..</p><p> // Finally set the flag to prevent continous carriage returns</p><p> transmissionEnded = true;</p><p> }</p><p> }</p><p>}</p>
<p>Well I've taken a look at the barebones example from the library you mentioned and it looks like it should be relatively simple to tack on the Morse code sending functionality (receiving would take some additional coding work, depending on how you wanted to accomplish it). I haven't tested it, but I would make the following additions to my code (line numbers are the current ones, they'll probably change as you add these lines of code in, so be careful)</p><blockquote>//towards the top of the code:<br></blockquote><blockquote>//additional includes for morse, insert after line #9<br></blockquote><blockquote>#include &lt;avr/pgmspace.h&gt;<br>#include &lt;MorseEnDecoder.h&gt;</blockquote><blockquote>//add object for sending morse, here defined as pin 13, after includes<br></blockquote><blockquote>morseEncoder morseOutput(13);</blockquote><blockquote>//no additions needed to void setup() assuming the library default of 13wpm is used</blockquote><blockquote>//add the following after lines 140 and 505</blockquote><blockquote>morseOutput.encode();</blockquote><blockquote>morseOutput.write(typedtext);</blockquote>
<p>thank you for your response.</p><p>morseOutput.write(typedtext); will not work.</p><p>char* to char compilation problem</p><p>instead i have used </p><p>for (int i=0; i&lt;(positionintypedtext); i++){</p><p> char sendMorse = typedtext[i];</p><p> morseOutput.write(sendMorse);</p><p>morseOutput.encode();</p><p>Serial.print(i);</p><p>Serial.print(sendMorse);</p><p>Serial.print(morseOutput.morseSignalString);</p><p>}</p><p>everything works in the serial window but no morse code.</p>
<p>Did you try the for loop with the morseOutput.encode(); before the morseOutput.write(sendMorse); rather than after? That seemed to be the order it had to be in. Also just to make sure, what are you using to check for the Morse output?</p>
<p>this is the code that i am using right now.</p><p>void outputserial(){</p><p> morseInput.setspeed(13);</p><p> morseOutput.setspeed(13);</p><p> lastTransmissionTime = (long)millis();</p><p> for (int i=0; i&lt;(positionintypedtext); i++){</p><p> morseDecoder morseInput(morseInPin, MORSE_KEYER, MORSE_ACTIVE_LOW);</p><p> morseEncoder morseOutput(morseOutPin);</p><p> Serial.println();</p><p> Serial.print(i);</p><p> Serial.print(')' );</p><p>char sendMorse = typedtext[i];</p><p> morseOutput.write(sendMorse);</p><p> morseOutput.encode();</p><p> Serial.write(' ');</p><p> Serial.write(sendMorse);</p><p> Serial.write(' ');</p><p> Serial.write(morseOutput.morseSignalString);</p><p> }</p><p> delay(preventholddelay); //delay a little to prevent continuous cycling</p><p>}</p><p>it needs to be like that :</p><p>morseOutput.write(sendMorse);</p><p>morseOutput.encode();</p><p>otherwise i get nothing.</p>
<p>Here, I threw together some code to add to mine that should achieve Morse transmission... without the uncooperative library. Tack the variables to the top and the functions at the bottom, and call sendmorse() at lines 140 and 505.</p>
<p>i have just tryed it ! </p><p>did you try it on an arduino ?</p><p>it actualy goes inside the for loop for just one time and then it realy freezes.</p><p>it can not pass the for loop at all !</p><p>i had a Serila.println(i);</p><p>and it just comes up with 0.</p><p>never goes again inside the loop at all.</p><p>i will try to convert the ifs in to swich just in case that those are the delays.</p><p>one thing that actualy works as expected is the time from the press of the &quot; Enter &quot; key until the time that goes inside the for loop.</p><p>i excpected 5 seccond and it came up 5000 millis of deference, ech time i tryied it out.</p><p>after that it just freezes.</p>
<p>IT DOESN'T FREEZE.</p><p>at the time that i needed to right the previous post i left the Serial Window oppen</p><p>and this is the results that came up : </p><p>0 // i</p><p>8804 // millis that passed throug the loop</p><p>1 // i</p><p>183806 // millis that passed throug the loop</p><p>2 // i</p><p>358810 // millis that passed throug the loop</p><p>3 // i</p><p>533814 // millis that passed throug the loop</p><p>??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????</p><p>175002 millisecond delay between each pass through the for loop.</p>
<p>You may be right about the if statements causing delays, try changing them to switch/case and see what happens...</p>
<p>I don't have the hardware all set up anymore so I haven't been able to test the code.</p>
<p>Also another thing to check is that I noticed the code you had before individually was printing the letters to the serial console. If that is in the for loop you used, all those individual serial outputs can cause considerable delays, especially at low baud rates.</p>
<p>do you have any idea on how can i use this code to transmit everything in morse code and not to the serial ?</p>

About This Instructable




More by Clayton Ford:Replicating "Old-School" Texting with an Arduino, a 4x4 Numerical Keypad, and a 16x2 LCD 
Add instructable to: