Sida 2 av 3

Re: Styra Arduino via Android

Postat: 12 oktober 2011, 22:26:45
av mrfrenzy
Trevligt projekt! Vi vill såklart gärna se koden.

Jag kan också tipsa om att det går att skriva androidappar i python http://hameedullah.com/develop-your-fir ... ython.html

Det är så underbart enkelt att koda i python, exempel på en komplett app som fotar och scannar streckkod på en bok samt öppnar webbläsaren till google books med detta isbn:

Kod: Markera allt

import android
droid = android.Android()
code = droid.scanBarcode()
isbn = int(code['result']['SCAN_RESULT'])
url = “http://books.google.com?q=%d” % isbn
droid.startActivity(‘android.intent.action.VIEW’, url)

Re: Styra Arduino via Android

Postat: 12 oktober 2011, 23:32:36
av sodjan
OK, det där såg ju enkelt ut och jag skriver redan Python i andra miljöer.
Men, vilka steg tar man för att köra det där i en telefon !?

Re: Styra Arduino via Android

Postat: 13 oktober 2011, 07:34:36
av kenntoft
Jag håller verkligen med om att Python är underbart att programmera i.

Slodjan: Du kan plocka min kod som jag lägger upp om du vill göra en app i Eclipse.
Ska bara lägga upp koden först:) måste även kommentera lite, har fixat en del med bilen på sistone så jag har inte haft så mkt tid. Lägger även upp en färdig att installera APK-fil.

Om du vill göra appen i Python så kan jag inte hjälpa dig. Däremot kan jag slänga upp min Python webserver kod.

Re: Styra Arduino via Android

Postat: 13 oktober 2011, 09:54:04
av mrfrenzy
sodjan: jag har inte provat själv ännu, ingen tid.... På hameedullah-länken står hur du sätter upp utvecklingsmiljön.
I kommentarerna finns en länk till hur man paketerar det som en app som vem som helst kan installera utan utvecklingsmiljön.

Re: Styra Arduino via Android

Postat: 13 oktober 2011, 11:57:12
av kenntoft
Aaah SL4A, jag funderade på det i början, vet inte varför jag övergav det dock.
Om man har ett "Android <-> BT <-> Arduino" interface kan jag se många fördelar med det.

Men jag har lite idéer för framtiden och då vill jag helst inte vara begränsad till BT.
Kan vara ett bra komplement däremot, vi får se!!

Jättebra länk förresten, väldigt pedagogisk.

EDIT: Nyttiga länkar som jag använt:

Installera Eclipse & Android SDK på Ubuntu (Linux)
http://www.mdl4.com/2011/06/how-to-inst ... in-ubuntu/

Installera Eclipse & Android SDK på Win7
http://www.mikeplate.com/2010/11/01/ins ... windows-7/

Hur man installerar en app Android telefonen:
http://maketecheasier.com/install-appli ... 2011/01/28

För dom som vill fräscha upp Arduino kunskaperna, en superb Arduino tutorials sida (bästa jag stött på):
http://tronixstuff.wordpress.com/

Jag körde ett tag på win7 men jag hoppade till Ubuntu för att underlätta med Python och programmera Python webserver

Re: Styra Arduino via Android

Postat: 13 oktober 2011, 19:38:50
av kenntoft
Här är Arduino sketchen.
Använde följande kopplingschema:
Bild

Kod: Markera allt

#include <LiquidCrystal.h> 
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);   //init the display pins
String str1 = "Ready to start";          //A welcome string

void setup(){
  lcd.begin(16, 2);
  Serial.begin(9600);
  lcd.print(str1);      //print welcome string on startup
  pinMode(13, OUTPUT);  //Pin 13 as output, the pin with the led connected

}

void loop()
{

  //this part will fill an array with data from the serial one character at the time
  char charArray[200]; //200 
  if (Serial.available()>0)
  {
    
    int i = 0;
    String commandString = "";
    while(Serial.available() > 0)
    {
      
      charArray[i] = Serial.read();
      delay(10);
      commandString = commandString + (charArray[i]);
      i++;
    } //while loop
    
    //char Read = Serial.read(); //used for trouble-shooting
    charArray[i] = '\0';
    switch (charArray[0])  // case for first character
    {
      case '#':  //turn on led if char is #
      digitalWrite(13, HIGH);
      break;  
      
      case ';': //turn off led if char is ";" | original "%" did not work
      digitalWrite(13, LOW); 
      break;
     
      default: //default is print the text sent
          delay(50);
          lcd.clear();
          lcd.print(commandString); //print the strin
          //Serial.print(commandString + '\n'); // use for trouble-shootin 
    } //switch bracket
    
 
    } //if serial bracket
    //random number, this can be changed to a sensor value with analogRead();
    delay(1000);  //seems like any quicker than this will slow it down
    int randNo = random(1,100); //random(min, max)
    Serial.println(randNo);  
} //void loop

Re: Styra Arduino via Android

Postat: 13 oktober 2011, 20:16:31
av kenntoft
Python webserver kod

Kom ihåg att ni stänger av Apache webserver först innan ni startar Python webserver

Stoppa Apache webserver:
sudo /etc/init.d/apache2 stop
Starta Python webserver (OBS, kommer inte starta om den inte får träff på serial-port):
sudo python /usr/share/pype/webserver/webserver.py
Du stoppar den sen med CTRL+C

Sammanfattningsvis kan man beskriva det så här:
Appen skickar en POST eller GET till webservern, som svarar.
POST skickas vidare till Arduino, som tittar på första tecknet
case # = led on
case ; = led off
else = skriv ut på display
Vid en GET request så hämtar Python vad det står i serial-port, typ "523"
Som sen Python skriver till din Android telefon.

Kod: Markera allt

# based on Jon Berg , turtlemeat.com, httpserver
# Tweaked for my purposes by Jonas Kenntoft
#!/usr/bin/env python

import string, time, serial
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer

#init the serial device
ser = serial.Serial(                            
    port='/dev/ttyACM0',
    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS)  

class MyHandler(BaseHTTPRequestHandler):

    #handle GET requests to webserver (our sensor value)
    def do_GET(self):
        try:
            #when Android phone requests to see whatever +".html" this happens:
            if self.path.endswith(".html"):
                #you can put whatever stuff here right now nothing happens.
                #maybe you want to get a seperate sensor value.
                self.send_response(200)
                self.send_header('Content-type',	'text/html')
                self.end_headers()
                return
            #when Android phone requests to see "/index.esp" this happens:
            if self.path.endswith(".esp"):   #esp is just random, 
                #can use any ending, make sure your android app uses it.
                
                #html responses, very necessary
                self.send_response(200)
                self.send_header('Content-type',	'text/html')
                self.end_headers()
                #Read sensor values
                read_txt = ser.readline() #read from serial and put it into var read_txt
                self.wfile.write(read_txt)      #write out read_txt to requestor (your android phone)
                return
                
            return
                
        except IOError:
            self.send_error(404,'File Not Found: %s' % self.path)
     
    #handle POST requests to webserver (our text message)
    def do_POST(self): #whenever webserver recieves POST do this:

        ser = serial.Serial( #init Arduino                           
        port='/dev/ttyACM0',
        baudrate=9600,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS)  
           
        #we can use endswith() to make difference for multiple posts
        post_str = self.path #POST string is in the path posted, 
        
        #post_str[1:] returns the characters after the first (0) in our case that is "/"
        #for example we send HELLO from phone, the server recieves "/HELLO"
        #and for LED ON "/#", LED OFF "/;" etc.
        ser.write(post_str[1:])
        
        #html responses, very necessary
        self.send_response(200)
        self.send_header('Content-type',	'text/html') 
        self.end_headers()
        #ser.close() #found it not to be neccessary to close the serial connection, but might be useful.
        

def main():
    try:
        server = HTTPServer(('', 80), MyHandler)
        print 'started httpserver...' #Webserver starting message
        server.serve_forever()
    #Stop server with CTRL+C    
    except KeyboardInterrupt:
        print '^C received, shutting down server'
        ser.close() #I put the serial.close() here
        server.socket.close()

if __name__ == '__main__':
    main()


Re: Styra Arduino via Android [Nu med kod]

Postat: 13 oktober 2011, 20:21:22
av blueint
Lägger man pythonservern som CGI skript så slipper man stanna den ordinarie http servern. Kräver iofs lite omskrivning.

Re: Styra Arduino via Android [Nu med kod]

Postat: 13 oktober 2011, 20:24:12
av kenntoft
Blueint: ja det är ju sant!

Men jag tycker de funkar bra med en python server bara, men för såna som tänkt använda en webserver till annat så är det en bra idé.
För python och CGI kommer ju så bra överens :)

Re: Styra Arduino via Android [Nu med kod]

Postat: 13 oktober 2011, 20:56:06
av kenntoft
Android app kod

Senaste videon, EM-kval i bakgrunden så man var lite ofokuserad.
http://www.youtube.com/watch?v=NMCwcS6b2Zs

Ni behöver SendToPhp.java, STRINGS.XML och MAIN.XML i erat projekt.
Zippade hela min projektmapp, hoppas det funkar, APK filen är den färdiga filen redo att installeras på Androidluren.

För att appen vill använda Internet så måste ni lägga till:

Kod: Markera allt

<uses-permission android:name="android.permission.INTERNET"></uses-permission>
I eran AndroidManifest.xml fil.
Snippen ska ligga ovanför <uses-sdk>

SendToPhp.java
Ganska mycket kod, men det är många funktioner oxå :)
Den börjar med att importera allt nödvändigt.
Kom ihåg att den första raden package send.toPHP är ditt projekt namn i Eclipse.
Nu använder jag mig inte av PHP längre men skitsamma.

Kod: Markera allt

package send.toPHP;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;


public class SendToPhp extends Activity {
	private EditText text; //input text
	private EditText ipString; //ip number string
	private TextView textRandom; //the sensor value, which is random right now
	private Timer autoUpdate;
	private ToggleButton OnOff; //on off switch value
	private SeekBar seekBar; 
	private ToggleButton ipConnect; //connect button value
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		text = (EditText) findViewById(R.id.textBox);
		ipString = (EditText) findViewById(R.id.ipBox);
		OnOff = (ToggleButton) findViewById(R.id.ledOnOff);
		seekBar = (SeekBar) findViewById(R.id.seekBar1);
		textRandom = (TextView) findViewById(R.id.randomBox);
		textRandom.setText("0"); //make the random number 0 on start-up
		ipConnect = (ToggleButton) findViewById(R.id.connectButton);
	       
		final TextView seekBarValue = (TextView)findViewById(R.id.seekBarValue);
	       
	    seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){

//this is the slide bar, does NOTHING right now but I want to combine with PWM
	   @Override
	   public void onProgressChanged(SeekBar seekBar, int progress,
	     boolean fromUser) {
	    // TODO Auto-generated method stub
	    seekBarValue.setText(String.valueOf(progress));
	   }

	   @Override
	   public void onStartTrackingTouch(SeekBar seekBar) {
	    // TODO Auto-generated method stub
	   }

	   @Override
	   public void onStopTrackingTouch(SeekBar seekBar) {
	    // TODO Auto-generated method stub
	   }
	       });
	   }    
	

//Here starts the post http function 
	public void postData(View view) {
    // Create a new HttpClient and Post Header
	//post data to web-server
	
	try {
		String IpNo = ipString.getText().toString();  //ip number
		String text_write = text.getText().toString(); //take the text from input text 
        HttpClient client = new DefaultHttpClient(); 
        //by posting like this the server will process the text_write string
        
        String postURL = "http://" + IpNo + "/"+ text_write; 
        HttpPost post = new HttpPost(postURL);
            //this part is not necessary because I only post on single line, but kept it for the future.
        	List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("text1", text_write)); 
            params.add(new BasicNameValuePair("text2", "")); //not actually in use, just empty
            UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params,HTTP.UTF_8);
            post.setEntity(ent);
            HttpResponse responsePOST = client.execute(post);  
            HttpEntity resEntity = responsePOST.getEntity();  
            if (resEntity != null) {    
                Log.i("RESPONSE",EntityUtils.toString(resEntity));
            }
            //Toast code: simply sends "Text sent!"-alert after button click
            Context context = getApplicationContext(); 	//not sure what this is
            CharSequence text = "Text sent! " + "'" + text_write + "'";			//Toast text
            int duration = Toast.LENGTH_SHORT;			//Duration of the toast

            Toast toast = Toast.makeText(context, text, duration);
            toast.show();
            
    } //try
		catch (Exception e) {e.printStackTrace();}//catch
	}//post
	

	//Here starts the ON/OFF logic
	public void f_onOff(View view) {
		    // Create a new HttpClient and Post Header
			//post data to web server
	
		if (OnOff.isChecked()) { //if onOff button is checked do this:
				/*int duration1 = Toast.LENGTH_SHORT;	
				Context context1 = getApplicationContext();
				CharSequence text = "On";
		 		Toast toast = Toast.makeText(context1, text, duration1);
	            toast.show();*/ //good for trouble-shooting
	            
	            try {
		            String IpNo = ipString.getText().toString(); //get the IP address from the ipBox
		            String strOn = "#";  //the LED ON character recognized by Arduino
		            HttpClient client = new DefaultHttpClient();  
		            String postURL = "http://" + IpNo + "/"+ strOn; //post this to the server to initiate server side functions
		            HttpPost post = new HttpPost(postURL);
		                HttpResponse responsePOST = client.execute(post);  
		                HttpEntity resEntity = responsePOST.getEntity();  
			                if (resEntity != null) {    
			                    Log.i("RESPONSE",EntityUtils.toString(resEntity));
			                    }//if
			                else{}
	            }
	            catch (Exception e) {e.printStackTrace();}
	            

		}//if
		 else{ //if the onOff button is NOT checked do this:
		 		/*int duration2 = Toast.LENGTH_SHORT;	
		 		Context context2 = getApplicationContext(); 	//not sure what this is
		 		CharSequence text = "off";
		 		Toast toast = Toast.makeText(context2, text, duration2);
	            toast.show();*/ //good for trouble-shooting

	            try {	
		            String IpNo = ipString.getText().toString(); //get the IP address from the ipBox
		            String strOff = ";"; //the LED OFF character recognized by Arduino
		            HttpClient client = new DefaultHttpClient();  
		            String postURL = "http://" + IpNo + "/"+ strOff; //post this to the server to initiate server side functions
		            HttpPost post = new HttpPost(postURL);
		                HttpResponse responsePOST = client.execute(post);  
		                HttpEntity resEntity = responsePOST.getEntity();  
		                if (resEntity != null) {    
		                    Log.i("RESPONSE",EntityUtils.toString(resEntity));
		            	}//if
		                else{}
	            }//try
		        catch (Exception e) {e.printStackTrace();}
		 }//else

	 }	//LED control stops here            

//Here starts the random text box function
	public void f_random(View view){
		if (ipConnect.isChecked()) { //make sure that we are connected if connected, do this:
			
		try {
				String IpNo = ipString.getText().toString();
				HttpClient client = new DefaultHttpClient();  
		        String getURL = "http://" + IpNo + "/index.esp";
		        HttpGet get = new HttpGet(getURL);
		        HttpResponse responseGet = client.execute(get);  
		        HttpEntity resEntityGet = responseGet.getEntity();  
		        if (resEntityGet != null) {  
		        			textRandom.setText(EntityUtils.toString(resEntityGet));
		                    Log.i("GET RESPONSE",EntityUtils.toString(resEntityGet));
		                }//if
		}//try 
		catch (Exception e) {e.printStackTrace();}
			}
		else{} //if not connected do nothing
	}

//Here starts the re-run random text box, it has a auto-update function.
		@Override
		 public void onResume() {
		  super.onResume();
		  autoUpdate = new Timer();
		  autoUpdate.schedule(new TimerTask() {
		   @Override
		   public void run() {
		    runOnUiThread(new Runnable() {
		     public void run() {
		      f_random(textRandom);
		     }
		    });
		   }
		  }, 0, 5000); // updates each 5000 millisecond (5 sec)  //if troubleshooting put some huge number
		 }

		 @Override
		 public void onPause() {
		  autoUpdate.cancel();
		  super.onPause();
		 }
		//Here stops the refresh logic


} //activity bracket
STRINGS.XML
Här lagras strängar, typ knapp text och färger, osv.

Kod: Markera allt

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Write to Arduino:)</string>
    <string name="app_name">Hello Arduino</string>
    <color name="myColor">#3399CC</color>
    <string name="postData">postData</string>
    <string name="SendToHttp">Send</string>
    <string name="ip_string">IP:</string>
    <string name="random">Sensor value:</string>
    <string name="onOff">onOff</string>
    <string name="seekbarvalue">seekbarvalue</string>
</resources>
MAIN.XML
Kan man säga att detta är GUIn?, alla knappar/boxar/etc.

Kod: Markera allt

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@color/myColor"
    >
    
    <EditText 
    android:id="@+id/textBox"
    android:layout_width="250dp" 
    android:layout_height="wrap_content" 
    android:inputType="text" 
    android:paddingTop="0dp" 
    android:maxLength="16"
    android:layout_marginLeft="60dp" >
    <requestFocus></requestFocus>
    </EditText>
    
    <Button 
    android:id="@+id/SendToHttp" 
    android:layout_gravity="center_horizontal" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:onClick="postData" 
    android:text="@string/SendToHttp" 
    android:layout_below="@+id/editText1"></Button>
    
    <TextView 
    android:id="@+id/ipText"
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="@string/ip_string" 
    android:layout_below="@+id/SendToHttp" 
    android:layout_marginTop="10dp"
    android:layout_marginLeft="15dp" 
    android:textStyle="bold" 
    android:textSize="20dp" 
    ></TextView>
    
    <EditText 
    android:id="@+id/ipBox"
    android:layout_height="wrap_content" 
    android:text="192.168.1.103" 
    android:layout_width="171dp" 
    android:layout_marginLeft="50dp" 
    android:layout_below="@+id/SendToHttp" 
    ></EditText>
    
    <TextView 
    android:id="@+id/toggleText" 
    android:layout_width="wrap_content" 
    android:layout_height="50dp"
    android:layout_alignLeft="@+id/textView2"
    android:layout_marginTop="25dp" 
    android:layout_below="@+id/ipText" 
    android:text="LED switch"
    android:textStyle="bold" 
    android:textSize="15dp"  
    ></TextView> 
    
    <ToggleButton 
    android:id="@+id/connectButton"
    android:layout_height="wrap_content" 
    android:layout_width="wrap_content" 
    android:layout_below="@+id/textBox" 
    android:layout_alignLeft="@+id/ipBox"
    android:layout_marginLeft="180dp"
    android:layout_marginTop="3dp"
    android:textOff="Connect"
    android:textOn="Connected"
    android:onClick="f_random"
    ></ToggleButton>
       
    <ToggleButton android:id="@+id/ledOnOff"
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_below="@+id/ipText" 
    android:layout_marginTop="15dp"
    android:textOff="Off"
    android:textOn="On"
    android:layout_marginLeft="85dp" 
    android:onClick="f_onOff"
    ></ToggleButton>
       
    <TextView android:id="@+id/randomBox" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"
    android:text="[random no]" 
    android:layout_below="@+id/ledOnOff" 
    android:textStyle="bold" 
    android:textSize="20dp" 
    android:layout_marginLeft="135dp"></TextView>
    
    <TextView android:id="@+id/randomText"
    android:layout_width="wrap_content" 
    android:layout_height="50dp"
    android:layout_alignLeft="@+id/textView2"
    android:layout_marginTop="0dp" 
    android:layout_below="@+id/ledOnOff" 
    android:text="@string/random"
    android:textStyle="bold" 
    android:textSize="20dp"  
    ></TextView>
    
    <SeekBar android:id="@+id/seekBar1" 
    android:layout_width="150dp" 
    android:layout_height="wrap_content" 
	android:layout_below="@+id/randomText"
	></SeekBar>
	
    <TextView 
    android:id="@+id/seekBarValue"
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Value" 
    android:layout_alignTop="@+id/seekBar1" 
    android:layout_alignRight="@+id/ipBox" 
    ></TextView>
   
</RelativeLayout>

Re: Styra Arduino via Android [Nu med kod]

Postat: 18 oktober 2011, 22:44:46
av kenntoft
haha där tappade alla intresset ;P

Anyway om någon vill ge sig på något liknande så är jag här :)

Re: Styra Arduino via Android [Nu med kod]

Postat: 18 oktober 2011, 22:48:55
av wombat
Superintressant, har bara inte tid för ett till projekt! :roll:

Ser dock enorma möjligheter, och Arduino fuskar jag ju redan lite med.

Återkommer! :tumupp:

/W

Re: Styra Arduino via Android [Nu med kod]

Postat: 18 oktober 2011, 22:50:36
av kenntoft
Wombat:

Haha tack för det!
Hur som helst så tycker jag att det har massor med potential.

Lycka till med ditt projekt och kom tillbaka sen om du behöver ett till projekt;P

Re: Styra Arduino via Android [Nu med kod]

Postat: 18 oktober 2011, 23:29:39
av Glenn
kenntoft skrev:haha där tappade alla intresset ;P
Nä, tvärtom :)

..Om man nu bara hade lite mer tid också..

Re: Styra Arduino via Android [Nu med kod]

Postat: 18 oktober 2011, 23:35:24
av kenntoft
Glenn :

Jag skrev bara så för det vart så himla tyst när jag postade koden.
Det är inte så komplicerat egentligen.

Har däremot hittat en bugg :D eller alltså jag hade det inte förut men nu har jag det.
När jag skickar en text-sträng, och bara den första efter RESET så kommer bara 1-3 tecken fram till displayen...
vet inte varför, speciellt eftersom det funkat förut ;P

Men det felet måste ligga på webb-servern eller i Arduino sketchen.

Nåväl.
Är upptagen med RGB LED bordet nu, men där vill jag nog applicera min App.
Synd bara att jag måste hänga på en PC på ARduinon. men jag har en laptop utan skärm som man kan hänga på till jag skaffar typ en ethernet shield eller kanske en blue-tooth shield till Arduinon.