One of the main motivations for adding asynchronous CDC support code to rev.2.0 of USB Host Library was to be able to use cell phones in Arduino projects – establish simple data exchange via SMS, take pictures or connect to the Internet. Second hand phones are inexpensive yet quite capable. Also, m2m (machine to machine) SIM cards start at $4-$6/mo, some even allow for free incoming SMS. All that makes a cell phone an attractive communication option for hobby projects. In this post, I will be talking about basics of cell phone control using data port and AT commands. I will also present simple terminal emulator sketch – to use the code you will need an Arduino board, USB Host Shield, as well as USB Host Shield 2.0 library.
Modern (<10 year old) phones have standard gsm chip interface implemented and accessible via so-called "data port". the oldest implement ttl level asynchronous serial by means of "custom" usb data cable, which is just proprietary connector on one end, other usb-to-serial converter (almost always prolific pl2303) between them. newer cell built-in. motorola usually terminate port mini-usb connector, others, like samsung sony ericsson, use cable. in these almost cdc acm type.
many functions phone can be accessed at commands, similar to commands used control hayes modems. are defined 3GPP TS 07.07 (look for the latest version, which is 7.8.0). Cell phone manufacturers also define their own AT commands. In documentation AT commands are usually presented in uppercase, however, most phones accept lowercase just as well. A command shall be followed by CR,LF (usually Enter key). If a command is accepted, OK is returned, along with response. If command is not recognized, ERROR is returned. Some commands will be accepted in certain phone states and rejected in others.
There are several variants of invoking each command:
-
Execute This variant is used for commands which require no parameters. The format is
ATcommand
. For example, the following command returns power source and battery charge level:
AT+CBC+CBC: 2,66
OK
The response means that a phone is powered from external power supply (2) and battery level is 66 percent. -
Test This variant is used to query parameters and their values for the command. The format is
ATcommand=?
.
AT+CIND=?
+CIND: ("Voice Mail",(0,1)),("service",(0,1)),("call",(0,1)),("Roam",(0-2)),("signal",(0-5)),("callsetup",(0-3)),("smsfull",(0,1))OK
This command outputs all indicators available on the phone screen, and their possible values. -
Get This variant is used to query current settings for the command. The format is
ATcommand?
.
AT+CIND?
+CIND: 0,1,0,0,4,0,0OK
Comparing to output of previous “Test” variant of the same command we can see that “Service” indicator on the phone screen is on and “signal” indicator is at level 4.
-
Set This variant is used to change settings for the command. The format is
ATcommand=param,param...
.
AT+CKPD="1"
OK
This command simulates a keypress on phone keypad. The key pressed is number “1”. -
Unsolicited response is output of some event other than command result. The format is
+COMMAND:result
. It is the same as command response sans command itself. Take a look at the following example:A
+CMER
command enables or disables sending of unsolicited result codes in the case of key pressings, display changes, and indicator state changes. The parameters for this command are as follows:
AT+CMER=?
+CMER: (0,3),(0,1,2),(0),(0,1,2),(0)
OK
First parameter sets output mode, next three parameters turn output on or off for keypad, display and indicator. Last parameter controls buffering. On Motorola RAZR, the default state of this command is as follows:
AT+CMER?
+CMER: 0,0,0,0,0
OK
which means all responses off. Now, if we turn reporting on and set keypad to on:
AT+CMER=3,1,0,0,0
OK
and start pressing buttons on the phone, we will see the following:
+CKEV: "E",1
+CKEV: "E",0
+CKEV: "1",1
+CKEV: "1",0
+CKEV: "2",1
+CKEV: "2",0
+CKEV: "3",1
+CKEV: "3",0
+CKEV: "E",1
+CKEV: "E",0
Here, “E” means “Red” button (the one used to turn phone on/off, terminate a call, abort an action and many other things), “1”, “2”, and “3” are numerical buttons, and number after the comma means “press” if 1 and “release” if 0. It is now evident that I first pressed “Red” button to turn screen on, then pressed “123” and then pressed “Red” button again to erase the digits.
The following sketch is a simple terminal program. Only main loop is shown, Full text is available in examples directory on gitHub. Compile it, load, attach your phone to the USB host shield and open the terminal window. If a phone is detected successfully, sketch outputs configuration descriptor and waits for keyboard input.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | void loop() { Usb.Task(); if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) { uint8_t rcode; /* reading the keyboard */ if(Serial.available()) { uint8_t data= Serial.read(); /* sending to the phone */ rcode = Acm.SndData(1, &data); if (rcode) ErrorMessage<uint8_t>(PSTR("SndData"), rcode); }//if(Serial.available()... delay(50); /* reading the phone */ /* buffer size must be equal to max.packet size */ uint8_t buf[32]; uint16_t rcvd = 32; rcode = Acm.RcvData(&rcvd, buf); if (rcode && rcode != hrNAK) ErrorMessage<uint8_t>(PSTR("Ret"), rcode); if( rcvd ) { //more than zero bytes received for(uint16_t i=0; i < rcvd; i++ ) { Serial.print(buf[i]); //printing on the screen } } delay(10); }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. } |
Lines 10-16 contain sending part of the terminal. Keyboard buffer is checked and if not empty, a character is read and sent to the phone ( line 13, Acm.SndData()
). The rest of the loop() is reading the phone and it is a little more complicated.
When USB host sends IN transfer request to the phone, it doesn’t know how much data will be received. It could be one byte or it could be a big packet. That’s why the buffer allocated in line 22 must be equal to the maximum possible chunk of data, i.e. endpoint’s Max.packet size. Most phones have Max.packet size of 32 bytes, one notable exception being Samsung (64 bytes). If you see strange symbols and occasional Arduino resets while outputting large chunks of data, check Max.packet sizes of bulk endpoints and increase buffer size accordingly.
The request is sent in line 24. One important property of Acm.RcvData()
function is that it returns actual number of bytes received from endpoint. The loop in lines 28-32 uses rcvd
as a loop counter; this way, only part of the buffer filled during the transfer will be printed.
Now let’s start our terminal. Once a terminal session is open, commands can be entered from the keyboard. To check if connection is live, type at
and press Enter
. If phone is alive, you should see it replying with OK
. The next command to try is AT+CLAC
. This command outputs all supported commands. Other commands can be tried “by hand”; also, it is possible to get key codes with AT+CMER
, as was described earlier.
As cool as it may look, entering commands from the keyboard is not very useful for automation. It is desirable to have functions to call numbers, send and receive SMSes and browse the Internet. Luckily for us, such software has already being developed. There are several GSM shields on the market, and GSM/GPRS modules these shields are based on are almost identical to GSM phones. For example, I was able to follow most part of this tutorial using Motorola RAZR phone. Some commands are different but most work. Many commands described on this page also work. Finally, there is very well written GSM Playground Arduino Library, which can easily be modified to use USB methods to send/receive data to the phone. I’m planning on looking into it after finalizing new USB Host library.
Finally, I want to talk a little about compatibility. I checked this sketch with Motorola RAZR, Motorola V220 and Samsung A-777. Motorola phones work out of the box, Samsung requires changing buffer size. I also tried Sony Ericsson TM-506 and TM-717 – the configuration descriptor in these phones is very complex and the Init()
method won’t initialize them correctly. This will be fixed in the future. I’m also curious about other phones – please let me know if your phone worked with this sketch.
Oleg.
Just started today looking at remote control over Wi Fi and display remotely of video from a Nokia Phone. I have found readymade software that will send the video over wi fi. Issue now is control path between host computer indoors and the phone and its robot mover outside.
Thanks for the info great help in seeing what might be possible with different tyoes of hardware.
Folks,
I’m trying to use the acm_terminal sketch to talk to blackberry tour via an arduino with a usb shield. I don’t seem to be able to get the thing to take AT commands.. I think htere’s something wrong with the USB open.. I put in some code to print out the USB state and see I’m getting a USB_ERROR.
Here’s the add I made to acm_terminal
…
int g=0;
…
void loop()
{
Usb.Task();
if (Usb.getUsbTaskState() != g) {
Serial.println(Usb.getUsbTaskState(),HEX);
g = Usb.getUsbTaskState();
}
…
Here’s the results I get.. :
Start
20
30
40
50
80
ACM Init
Addr:1
NC:1
A0
note from usb.h I see
A0 maps to USB_STATE_ERROR
Any thoughts ? Thanks !
-jc
What does ACM::Init() return? In other words, does it detect your device?
Oleg,
Thanks for the response ! Where do I find ACM::Init() and how would I call it from that sketch ? I see it in cdcacm.cpp but I don’t see any code that calls it.
-jc
It’s called automatically from USB::Task() when it’s time to initialize a device. The purpose of Init() is to recognize a device and plug some data structures into USB system if device is detected successfully. Init() should return zero if successful.
I modified Usb.Task() to to return the usb_state..
looks like it’s HEX A0
-jc
This is correct. Look at Usb.cpp line 480, that’s the place where Task() state machine switches to error state (0xa0). Something happens during Init(), which is called from Configuring() at line 476. You may want to find out how your device’s configuration descriptor looks like.
No Oleg, it works not:(
I tryed it with Nokia 5500 – it stops in OnInit with SetControlLineState error.
Trying to connect it to a huawei K3765 3G modem but only this who’s up in terminal:
Start
ACM Init
Addr:1
NC:1
Any suggestions?
How you going with this ?
with what?
How is it progressing to connect a 3G Modem to the USB host shield and how is it done is my question
Hello anybody there?
Oleg has anybody connected your board to a USB plug in 3G modem ? If so can you give me any references please
Which one? Do you have a link to it? I have one bought at Dealextreme, haven’t had time to try it yet but it should be accessible using pl2303 code.
OK we can keep to and froing as long as you like but I am asking if you have got anywhere with this and if so how ? . If you havn’t then can you be more specific as to what I should do to get it connected?. Your knowledge of these matters is obviously extensive and I have ended up with one of your boards via a deceased estate and I would like to get it running.
HID programs and others appear to be running properly on your board but nothing connects to the 3G Modem
According to this -> http://blog.pew.cc/blog/Huawei+E160+and+Linux/ your device starts in mass storage mode and has to be switched to serial in order to be used as a modem. My drivers were developed for serial devices and won’t work with it.
Yes OK Thanks .
modeswitch is the program to run first then to switch to the modem. In fact it has 3 areas(modes) USB mini storage ,another storage internal which shows as a CD and the Modem. So I guess then I must get it to Modem somehow before running your programs . Well that does not seem that hard to do . I’ll work on it.I wonder if your program reads the other two modes.Don’t answer that . I will look and try for myself. Cheers
Huawei 160E
http://3g-modem.wetpaint.com/page/Huawei+E160+%28E160G%2C+E160E%2C+E160X%2C+K3565%29
Same as the above I think
I notice it may start in USB storage mode but it connects itself to the network-the blue light flashes rythmically. Whilst in that mode (which is only achievable by supplying additional voltage to the arduino by battery)…the program usb hub gives out the following
Start
01
—
Device descriptor:
Descriptor Length: 12
Descriptor type: 01
USB version: 0200
Device class: 00
Device Subclass: 00
Device Protocol: 00
Max.packet size: 40
Vendor ID: 12D1
Product ID: 1003
Revision ID: 0000
Mfg.string index: 02
Prod.string index: 01
Serial number index: 00
Number of conf.: 01
Configuration descriptor:
Total length: 0020
Num.intf: 01
Conf.value: 01
Conf.string: 03
Attr.: E0
Max.pwr: FA
Interface descriptor:
Intf.number: 00
Alt.: 00
Endpoints: 02
Intf. Class: 08
Intf. Subclass: 06
Intf. Protocol: 50
Intf.string: 00
Endpoint descriptor:
Endpoint address: 81
Attr.: 02
Max.pkt size: 0040
Polling interval: 00
Endpoint descriptor:
Endpoint address: 01
Attr.: 02
Max.pkt size: 0040
Polling interval: 00
Addr:1(0.0.1)
At this point I don’t know exactly what this all means. Maybe you do.
08, 06, 50 in interface Class, Subclass, Protocol indicates mass storage device.
Good stuff Thank You
Oleg,
still no luck.. now trying a Samsung SGH-a07 track phone.. I print out the return code from the call to Configuring in usb.cpp (line 476).. I also print the value of rcode in Configuring (about line 576).. It looks like it’s returning a HEX value of D
or decimal 13. Is that a clue ?
-jc
D means no reply; it usually happens when you send something unexpected to the endpoint like OUT transaction to IN endpoint. The Init() may try to configure it incorrectly. If you can, find old Motorola, like V180, V220, or RAZR – they are guaranteed to initialize correctly. Also, try to connect your phone to a Windows PC and see how it appears in Device Manager.
Hmm.. I don’t think i will be bale to find one of those phones.. .. but I’ll look.
When I try plugging the Samsung track phone into my windos pc it tries to install, but it comes in as an ‘unknown USB device’. I suspect that I need ot find soem drivers for it.. Is that a clue ?
-jc
it could be proprietary device – in this case it won’t work with my code which assumes standard ACM class USB to serial converter. Do you have configuration descriptor of your phone?
Oleg.. how would I fetch that ? I’d be happy to send it
-jc
you can use hub_demo sketch, with or without a hub. It will print configuration descriptors of all devices connected to a host.
Simple Question: When the cell phone is connected to the USB Host Shield is it always charging / Will the phone stay charged while connected to the shield?
Usually, yes; the charging speed would depend on the amount of current provided to VBUS. Obviously, if current is not sufficient for the phone circuit functioning plus extra for charging, the battery will keep draining.
Oleg,
I just got a V220 and it also does not work.. neither the hub_demo or acm_terminal stretches seem to ‘see’ the phone when I plug it into the usbshield.. I see the message ‘Start’ in the Com terminal and then nothing. I suspect it’s a baud rate issue as I can successfully talk to the phone from hyperterminal from my laptop and it answers AT commands. What should the phones’ baud rate be set at ? Any other ideas why my shield cant talk to this (or any other ) phone so far ? Thanks !
-jc
John,
Whatever baud rate you have in hyperterm should work. Have you tried to type AT after seeing ‘Start’? I own V220 and it was like the first phone that i tried, it worked with no issues. Now, I don’t understand why hub_demo won’t show anything – have you been able to communicate to _anything_ using USB Host Shield?
Oleg.
Oleg..
No.. I can’t say I’ve ever successfully talked to anything with this usb shield. Do you think I may have a bad board ? BTW. I’m using a 328-based duemilenueve . I’m also powering it through usb.. (ie no separate power).. could any of that be a problem ? Let me plug in some other USB things and see if I can see them
I’m trying other stuff like cameras and not seeing anything in the hub demo.. what do you think that means ?
-jc
What type of shield do you have? You should be able to get some sort of output with hub_demo from any USB device with or without a hub. You may have a bad board, too – try running this -> https://github.com/felis/USB_Host_Shield_2.0/blob/master/examples/board_qc/board_qc.pde and see if you get any errors.
it’s from Sparkfun .. no visible serial num.. Here’s the output I get from the device when hooked to my pc and the v220 (same result when I try with my blackberry 9630, a moto droid 2 and a canon powershot camera) . I notice there’s the word ‘failed’ in the GPIO test.. but it says the overall test passed. is this a normal readout ?
I eventually stop it since the output doesn’t change
Circuits At Home 2011
USB Host Shield Quality Control Routine
Reading REVISION register… Die revision 03
SPI long test. Transfers 1MB of data. Each dot is 64K……………. SPI long test passed
GPIO test. Connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, and so on
Test failed. Value written: 00 Value read: FF
Press any key to continue…
GPIO test passed.
PLL test. 100 chip resets will be performed
Resetting oscillator
Reset number 0 Time to stabilize – 689 cycles
Reset number 1 Time to stabilize – 691 cycles
Reset number 2 Time to stabilize – 689 cycles
Reset number 3 Time to stabilize – 691 cycles
Reset number 4 Time to stabilize – 689 cycles
Reset number 5 Time to stabilize – 689 cycles
Reset number 6 Time to stabilize – 691 cycles
Reset number 7 Time to stabilize – 689 cycles
Reset number 8 Time to stabilize – 691 cycles
Reset number 9 Time to stabilize – 689 cycles
Reset number 10 Time to stabilize – 690 cycles
Reset number 11 Time to stabilize – 689 cycles
Reset number 12 Time to stabilize – 691 cycles
Reset number 13 Time to stabilize – 689 cycles
Reset number 14 Time to stabilize – 690 cycles
Reset number 15 Time to stabilize – 689 cycles
Reset number 16 Time to stabilize – 691 cycles
Reset number 17 Time to stabilize – 689 cycles
Reset number 18 Time to stabilize – 691 cycles
Reset number 19 Time to stabilize – 689 cycles
Reset number 20 Time to stabilize – 691 cycles
Reset number 21 Time to stabilize – 689 cycles
Reset number 22 Time to stabilize – 691 cycles
Reset number 23 Time to stabilize – 689 cycles
Reset number 24 Time to stabilize – 691 cycles
Reset number 25 Time to stabilize – 689 cycles
Reset number 26 Time to stabilize – 691 cycles
Reset number 27 Time to stabilize – 689 cycles
Reset number 28 Time to stabilize – 691 cycles
Reset number 29 Time to stabilize – 689 cycles
Reset number 30 Time to stabilize – 689 cycles
Reset number 31 Time to stabilize – 689 cycles
Reset number 32 Time to stabilize – 689 cycles
Reset number 33 Time to stabilize – 689 cycles
Reset number 34 Time to stabilize – 689 cycles
Reset number 35 Time to stabilize – 689 cycles
Reset number 36 Time to stabilize – 689 cycles
Reset number 37 Time to stabilize – 689 cycles
Reset number 38 Time to stabilize – 689 cycles
Reset number 39 Time to stabilize – 689 cycles
Reset number 40 Time to stabilize – 689 cycles
Reset number 41 Time to stabilize – 689 cycles
Reset number 42 Time to stabilize – 689 cycles
Reset number 43 Time to stabilize – 689 cycles
Reset number 44 Time to stabilize – 689 cycles
Reset number 45 Time to stabilize – 689 cycles
Reset number 46 Time to stabilize – 689 cycles
Reset number 47 Time to stabilize – 689 cycles
Reset number 48 Time to stabilize – 689 cycles
Reset number 49 Time to stabilize – 691 cycles
Reset number 50 Time to stabilize – 689 cycles
Reset number 51 Time to stabilize – 691 cycles
Reset number 52 Time to stabilize – 689 cycles
Reset number 53 Time to stabilize – 690 cycles
Reset number 54 Time to stabilize – 689 cycles
Reset number 55 Time to stabilize – 690 cycles
Reset number 56 Time to stabilize – 689 cycles
Reset number 57 Time to stabilize – 690 cycles
Reset number 58 Time to stabilize – 689 cycles
Reset number 59 Time to stabilize – 690 cycles
Reset number 60 Time to stabilize – 689 cycles
Reset number 61 Time to stabilize – 691 cycles
Reset number 62 Time to stabilize – 689 cycles
Reset number 63 Time to stabilize – 691 cycles
Reset number 64 Time to stabilize – 689 cycles
Reset number 65 Time to stabilize – 691 cycles
Reset number 66 Time to stabilize – 689 cycles
Reset number 67 Time to stabilize – 690 cycles
Reset number 68 Time to stabilize – 689 cycles
Reset number 69 Time to stabilize – 691 cycles
Reset number 70 Time to stabilize – 689 cycles
Reset number 71 Time to stabilize – 691 cycles
Reset number 72 Time to stabilize – 689 cycles
Reset number 73 Time to stabilize – 691 cycles
Reset number 74 Time to stabilize – 689 cycles
Reset number 75 Time to stabilize – 691 cycles
Reset number 76 Time to stabilize – 689 cycles
Reset number 77 Time to stabilize – 689 cycles
Reset number 78 Time to stabilize – 689 cycles
Reset number 79 Time to stabilize – 689 cycles
Reset number 80 Time to stabilize – 689 cycles
Reset number 81 Time to stabilize – 689 cycles
Reset number 82 Time to stabilize – 689 cycles
Reset number 83 Time to stabilize – 689 cycles
Reset number 84 Time to stabilize – 689 cycles
Reset number 85 Time to stabilize – 689 cycles
Reset number 86 Time to stabilize – 689 cycles
Reset number 87 Time to stabilize – 689 cycles
Reset number 88 Time to stabilize – 689 cycles
Reset number 89 Time to stabilize – 689 cycles
Reset number 90 Time to stabilize – 689 cycles
Reset number 91 Time to stabilize – 689 cycles
Reset number 92 Time to stabilize – 689 cycles
Reset number 93 Time to stabilize – 689 cycles
Reset number 94 Time to stabilize – 689 cycles
Reset number 95 Time to stabilize – 689 cycles
Reset number 96 Time to stabilize – 691 cycles
Reset number 97 Time to stabilize – 689 cycles
Reset number 98 Time to stabilize – 690 cycles
Reset number 99 Time to stabilize – 689 cycles
Reset number 100 Time to stabilize – 691 cycles
Checking USB device communication.
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
Waiting for device …
I cannot offer you an opinion on Sparkfun shield.
ahhhh.. I though this was your device.. how can I get one of yours ?
They are available here -> http://www.circuitsathome.com/products-page/arduino-shields/
Will this work with a Mifi 2200 as easily as a Razr via USB?
What is Mifi 2200 – do you have a link?
http://cache.vzw.com/multimedia/mim/mifi_2200/mifi2200.pdf
It is popular. I am testing AT commands with VZaccess Manager now…
this would depend on which USB classes are implemented in this device.
Can I query it to find out with an AT command?
You can find out by looking at what drivers are used in Windows for this device. You’d need ACM, that’s the same driver which is used by Arduino UNO/2560.
In the device manager I see:
modem.sys
nwusbmdm_000.sys
nwusbser_000.sys
Does this mean it’s impossible?
It works from the PC with AT commands.
compare it with what is used for Arduino UNO, if you have it.
Regarding problems with detecting ACM: Can’t it be because phones act as several endpoints: ACM, Mass Storage etc, and the code might “lock on to” the wrong endpoint?
Just guessing.
I started experimenting with your example code today, so I’ll check what endpoints it finds.
Thanks for the library, by the way.
Anders
This is what I get back från an HTC Wildfire by using hub_demo (two interface descriptors with two endpoints each):
Device descriptor:
Descriptor Length: 12
Descriptor type: 01
USB version: 0200
Device class: 00
Device Subclass: 00
Device Protocol: 00
Max.packet size: 40
Vendor ID: 0BB4
Product ID: 0C8B
Revision ID: 0226
Mfg.string index: 01
Prod.string index: 02
Serial number index: 03
Number of conf.: 01
Configuration descriptor:
Total length: 0037
Num.intf: 02
Conf.value: 01
Conf.string: 00
Attr.: C0
Max.pwr: FA
Interface descriptor:
Intf.number: 00
Alt.: 00
Endpoints: 02
Intf. Class: 08
Intf. Subclass: 06
Intf. Protocol: 50
Intf.string: 00
Endpoint descriptor:
Endpoint address: 83
Attr.: 02
Max.pkt size: 0040
Polling interval: 00
Endpoint descriptor:
Endpoint address: 02
Attr.: 02
Max.pkt size: 0040
Polling interval: 00
Interface descriptor:
Intf.number: 01
Alt.: 00
Endpoints: 02
Intf. Class: FF
Intf. Subclass: 42
Intf. Protocol: 01
Intf.string: 07
Endpoint descriptor:
Endpoint address: 84
Attr.: 02
Max.pkt size: 0040
Polling interval: 00
Endpoint descriptor:
Endpoint address: 03
Attr.: 02
Max.pkt size: 0040
Polling interval: 00
The code looks for ACM interface descriptor (the one which has certain class, subclass, protocol combination). You have mass storage on the first interface and vendor-defined class on the second. If you are certain that the second interface is ACM, you can modify the criteria for conf.descriptor parser in Init() – look at cdcacm.cpp line 136.
You said RAZR…
Is the RAZR v3m somehow too different?
In Windows it uses these drivers by default:
Dmgr Susteen USB Cable
modem.sys
sustucam.sys
hub_demo:
nothing
PC terminal:
no ports show
But Device Manager / Susteen properties / Diagnostics works!
Do I need to install a different driver? How?
Help?
It won’t work on Sparkfun shield – test it on mine when you get it.
Thanks for saving me the time I would waste on Sparkfun Host.
Most of the AT commands respond with ERROR. Do I need a signal to test these? Do I need to upgrade the firmware?
Figured it out for Verizon RAZR V3m. First AT+MODE=2. Thanks for listening!
This is not required for your phone?
Do you have a list of supported commands already? ‘at+clac’ ?
at+cfun is not in the at+clac listing. I’ve noticed the phone stays on even when no related sketch is running. Because there is power to the phone in addition to the battery? What if I cut the V+ wire in the USB cable to the phone?
If you cut V+ host won’t be able to detect the device. You may try to switch V+ to 3.3V, there is a pair of jumpers on shield’s PCB marked VBUS PWR, open 5V and close 3.3V. If nothing helps, you can pull the battery off the phone and wire a switch to VBUS, for example, a P-type MOSFET.
I don’t understand how it could help using 3.3v. If it recognizes the connection it will not sleep.
Yours may be the only solution. Even with the battery in the phone, when you remove the USB power it sleeps, also closing the connection. Will use cheap relay that’s handy.
Hey Oleg,
thanks very much for providing your library. I got it running on a Seeeduino Mega ADK using a Huawei E160 UMTS stick. There was only to change the parsing arguments in cdcacm.cpp, remapping the SS pin and pulling the Reset pin of the Max3421 HIGH.
Now I have access to this modem on AT-level and will try to set up a data connection next.
While reviewing your code I saw you did a very good job.
But maybe you can have a look why all Nokia mobile phones (e.g. E51) responding a STALL in setting the linecoding. I read several posts here about this problem.
Thanky you.
It ‘s likely that config descriptor parser picks the wrong interface in Nokias. I have a couple of Sony Ericssons with like 10 different interfaces in the config doing the same. You probably need to change the parser.
Hello Chris,
I’m also trying to connect a Huawei UMTS but can’t manage to send AT commands to it (I’m in the very beginning of knowing Arduino and USB Shield).
Can you specify the values you used in ConfigDescParser (regarding class, subclass and protocol)? Changing the Huawei initialization mode: AT^U2DIAG=0 (device-only modem), it only exposes interface class FF (vendor specific), and the PC recognizes the UMTS modem and able to send AT commands through hyper terminal.
As specified in Usb.h the SS pin is configured for P10 (Arduino Uno) or P53 (Arduino Mega ADK), you mention that SS pin was remapped… can you tell what was done?
Thanks in advance.
@Oleg: fantastic work! Thanks…
Oleg..
OK.. now I shelved my sparkfun usb_host, bought your usb_host. and I’m having a different sort of problem.. When I run the hubdemo I get
Start
OSC did not start.
when I try board_qc I get
Circuits At Home 2011
USB Host Shield Quality Control Routine
Reading REVISION register… Die revision invalid. Value returned: 00
Unrecoverable error – test halted!!
0x55 pattern is transmitted via SPI
Press RESET to restart test
I’m using your usb_host version 2 code
any clues ? Thanks !
-jc
Do you have all 5 headers soldered in place, including 2×3 one?
Oleg… yes i do.. but I missoldered the 2×3 one and had to remove it to resolder it on the other side (d-oh !) .. I wonder if I damaged it. do you have any simple connectivity info I can check to see if i have an open there .. eg.. where does the ICSP connections go on your board ? (or should I just buy another board)..
sorry for my stupid mistake !
-jc
I’d at least try to fix it before buying another board. Here is the schematic -> http://www.circuitsathome.com/wp/wp-content/uploads/2011/02/UHS_20.pdf . All signals from ICSP connector are routed to level shifter ICs, should be easy to test with a multimeter. Also, if you broke any traces, you can solder wires directly to pins.
Oleg..
Looks like that did it.. the RST line of the ICSP was not connected. A little yellow wire and I’m back in biz. Can you confirm this QC report looks OK ? The device at the oter end is my Blackberry. I can’t get it to respond to AT commands from the AT_TERMINAL sketch.. but I suspect that’s blackberry weirdness.. I’ll try with my simple moto phone later..
Does this QC trace look OK ? Note there is a memory write error
Circuits At Home 2011
USB Host Shield Quality Control Routine
Reading REVISION register… Die revision 03
SPI long test. Transfers 1MB of data. Each dot is 64K……………. SPI long test passed
GPIO test. Connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, and so on
Test failed. Value written: 00 Value read: FF
Press any key to continue…
GPIO test passed.
PLL test. 100 chip resets will be performed
Resetting oscillator
Reset number 0 Time to stabilize – 690 cycles
Reset number 1 Time to stabilize – 689 cycles
Reset number 2 Time to stabilize – 690 cycles
Reset number 3 Time to stabilize – 689 cycles
Reset number 4 Time to stabilize – 689 cycles
Reset number 5 Time to stabilize – 690 cycles
Reset number 6 Time to stabilize – 688 cycles
Reset number 7 Time to stabilize – 690 cycles
Reset number 8 Time to stabilize – 689 cycles
Reset number 9 Time to stabilize – 690 cycles
Reset number 10 Time to stabilize – 689 cycles
Reset number 11 Time to stabilize – 690 cycles
Reset number 12 Time to stabilize – 689 cycles
Reset number 13 Time to stabilize – 690 cycles
Reset number 14 Time to stabilize – 689 cycles
Reset number 15 Time to stabilize – 690 cycles
Reset number 16 Time to stabilize – 689 cycles
Reset number 17 Time to stabilize – 690 cycles
Reset number 18 Time to stabilize – 689 cycles
Reset number 19 Time to stabilize – 690 cycles
Reset number 20 Time to stabilize – 689 cycles
Reset number 21 Time to stabilize – 690 cycles
Reset number 22 Time to stabilize – 689 cycles
Reset number 23 Time to stabilize – 690 cycles
Reset number 24 Time to stabilize – 689 cycles
Reset number 25 Time to stabilize – 690 cycles
Reset number 26 Time to stabilize – 689 cycles
Reset number 27 Time to stabilize – 690 cycles
Reset number 28 Time to stabilize – 689 cycles
Reset number 29 Time to stabilize – 690 cycles
Reset number 30 Time to stabilize – 689 cycles
Reset number 31 Time to stabilize – 690 cycles
Reset number 32 Time to stabilize – 689 cycles
Reset number 33 Time to stabilize – 690 cycles
Reset number 34 Time to stabilize – 689 cycles
Reset number 35 Time to stabilize – 690 cycles
Reset number 36 Time to stabilize – 689 cycles
Reset number 37 Time to stabilize – 690 cycles
Reset number 38 Time to stabilize – 689 cycles
Reset number 39 Time to stabilize – 689 cycles
Reset number 40 Time to stabilize – 689 cycles
Reset number 41 Time to stabilize – 689 cycles
Reset number 42 Time to stabilize – 689 cycles
Reset number 43 Time to stabilize – 689 cycles
Reset number 44 Time to stabilize – 689 cycles
Reset number 45 Time to stabilize – 689 cycles
Reset number 46 Time to stabilize – 689 cycles
Reset number 47 Time to stabilize – 689 cycles
Reset number 48 Time to stabilize – 689 cycles
Reset number 49 Time to stabilize – 689 cycles
Reset number 50 Time to stabilize – 689 cycles
Reset number 51 Time to stabilize – 689 cycles
Reset number 52 Time to stabilize – 689 cycles
Reset number 53 Time to stabilize – 689 cycles
Reset number 54 Time to stabilize – 689 cycles
Reset number 55 Time to stabilize – 689 cycles
Reset number 56 Time to stabilize – 689 cycles
Reset number 57 Time to stabilize – 689 cycles
Reset number 58 Time to stabilize – 690 cycles
Reset number 59 Time to stabilize – 689 cycles
Reset number 60 Time to stabilize – 690 cycles
Reset number 61 Time to stabilize – 689 cycles
Reset number 62 Time to stabilize – 690 cycles
Reset number 63 Time to stabilize – 689 cycles
Reset number 64 Time to stabilize – 690 cycles
Reset number 65 Time to stabilize – 689 cycles
Reset number 66 Time to stabilize – 690 cycles
Reset number 67 Time to stabilize – 689 cycles
Reset number 68 Time to stabilize – 690 cycles
Reset number 69 Time to stabilize – 689 cycles
Reset number 70 Time to stabilize – 690 cycles
Reset number 71 Time to stabilize – 689 cycles
Reset number 72 Time to stabilize – 690 cycles
Reset number 73 Time to stabilize – 689 cycles
Reset number 74 Time to stabilize – 690 cycles
Reset number 75 Time to stabilize – 689 cycles
Reset number 76 Time to stabilize – 690 cycles
Reset number 77 Time to stabilize – 689 cycles
Reset number 78 Time to stabilize – 690 cycles
Reset number 79 Time to stabilize – 689 cycles
Reset number 80 Time to stabilize – 690 cycles
Reset number 81 Time to stabilize – 689 cycles
Reset number 82 Time to stabilize – 690 cycles
Reset number 83 Time to stabilize – 689 cycles
Reset number 84 Time to stabilize – 690 cycles
Reset number 85 Time to stabilize – 689 cycles
Reset number 86 Time to stabilize – 690 cycles
Reset number 87 Time to stabilize – 689 cycles
Reset number 88 Time to stabilize – 690 cycles
Reset number 89 Time to stabilize – 689 cycles
Reset number 90 Time to stabilize – 689 cycles
Reset number 91 Time to stabilize – 689 cycles
Reset number 92 Time to stabilize – 689 cycles
Reset number 93 Time to stabilize – 689 cycles
Reset number 94 Time to stabilize – 689 cycles
Reset number 95 Time to stabilize – 689 cycles
Reset number 96 Time to stabilize – 689 cycles
Reset number 97 Time to stabilize – 689 cycles
Reset number 98 Time to stabilize – 689 cycles
Reset number 99 Time to stabilize – 689 cycles
Reset number 100 Time to stabilize – 689 cycles
Checking USB device communication.
Device connected. Resetting
Reset complete. Waiting for the first SOF…
Getting device descriptor
Descriptor Length: 12
Descriptor type: 01
USB version: 0200
Device class: 00
Device Subclass: 00
Device Protocol: 00
Max.packet size: 40
Vendor ID: 0FCA
Product ID: 8004
Revision ID: 0211
Mfg.string index: 01
Prod.string index: 0F
Serial number index: 0D
Number of conf.: 01
All tests passed. Press RESET to restart test
Congratulations, you’ve fixed it! Don’t pay attention to GPIO test failing – in order for it to pass you need to connect GPIN to GPOUT as shown in the output. The rest of the tests passed so your shield is ready to be used.
All working well.. getting sms’s on my razr now.. thanks Oleg
OK.. now I can do everythign I want using AT commands from the ACM_TERM app. I’m now interested to see if anyone has written a quick arduino sketch to read SMS msgs from the phone and do something with them.. eg. print them on the serial terminal , blink a light, etc .. Just wanted to check before I wrote my own. Know of anything like that ?
-jc
You can print SMS on a terminal by just issuing a command, see here -> http://www.circuitsathome.com/mcu/interfacing-arduino-to-usb-gprs-modem As far as more practical code, there are several packages developed for proprietary GSM modules; you can probably use one of those packages as a template and substitute proprietary commands with generic GSM ones.
Hmm.. things working well on my Moto V220 .. reading and writing SMS now.. but cannot delete them. the command ‘at+cmgl’ fetches all SMS but.. ‘at+cgmd’ throws an error.. Is there some other way to delete read msgs ?
-jc
it is ‘cmgd’, not ‘cgmd’. You need to give it msg index, i.e. ‘at+cmgd=1’, for example.
Hi hope someone can be of guidance.
I just got my usb host shield, I am wondering if someone has ever tried to use a bluetooth dongle connected to it and communicate with a mobile phone (through bluetooth of course)?
I would like to use mobile processing. Or is it easier to use a bluetooth module (instead of usb host shield) to achieve communication with my phone? Would be great if someone knows of a blog or source code to get me started. thanks
Oleg…
Sorry.. I mistyped.. I’m using at+cmgd=1 and get ERROR. I get the same thing when I use AT+cmgd=? If I turn on the diagnostics and look at return code (4) .. it means ‘not supported’. Some other commands like ‘at+cmgl’ work .. but others like ‘at+cmgr’ do not. Ever seen that ?
-jc
Here’s what I have on Motorola V220:
at+cmgl
...
...
+CMGL: 1708, "STO SENT", "17205607054"
I can come but abit late.
OK
at+cmgd=1708
OK
next
at+cmgl
won’t show this message. You need to pass index of a message tocmgd
. If you pass non-existing index,cmgd
returns error (as well asat+cmgd?
,at+cmgd=?
)cmgr
(read) should be similar, you need message index. On some phones, there are several message storages, you’ll have to switch to correct storage first.Am trying to use Arduino Uno to connect to a phone so that it can send an sms. The project in totality is a robot that can detect a fire then notify the person in charge via a preset i.d. Am using a tone decoder to sense the fire alarm. Any help??
I have the USB shield connected to a Motorola RAZR and have been successful in using several of the AT commands in the serial terminal. I wrote some code for the Arduino for commands to be executed via the Serial.println when I push a button. The commands come up in the terminal window but they don’t reach the phone. I am still pretty new to writing code and I could not figure out how to actually send the commands to the phone through the USB Shield. I think I might be missing something with a CR and LF.
Ultimately I want to send a text or photo based off a motion trigger.
You can’t use Serial.println() to send data to the phone. You need to use acm.SndData().
I can’t seem to get the Acm,SndData() function in the right spot to get the code to compile. I only see it in the code you wrote here. Do I need to do something with the “rcode”?
/* reading the keyboard */
if(Serial.available()) {
uint8_t data= Serial.read();
/* sending to the phone */
rcode = Acm.SndData(1, &data);
if (rcode)
ErrorMessage(PSTR(“SndData”), rcode);
}//if(Serial.available()…
I would like to send Acm.SndData(“AT+CKPD”1””); when I press the momentary switch so it tells the phone to that I am pressing #1. Once I can get this figured out I am sure that I can write the code to press all the right buttons to have the camera take a photo and send it to me.
You need to do something like that:
const char* ckpd_one_cmd = "AT+CKPD=1,0,0";
rcode = Acm.SndData( strlen( ckpd_one_cmd ), (uint8_t *)ckpd_one_cmd );
Have tried several different ways to get this code to compile, I keep getting these errors
Cell_phone_control_2:24: error: expected constructor, destructor, or type conversion before ‘=’ token
Cell_phone_control_2:32: error: ‘ACMAsyncOper’ has not been declared
Cell_phone_control_2:60: error: ‘ACMAsyncOper’ does not name a type
Cell_phone_control_2:61: error: ‘AsyncOper’ was not declared in this scope
Cell_phone_control_2.cpp: In function ‘void loop()’:
Cell_phone_control_2:122: error: expected primary-expression before ‘)’ token
Cell_phone_control_2:122: error: expected `;’ before ‘)’ token
looking for a constructor
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "pgmstrings.h"
#define BUTTON 7// here is the button that I put in
int val =0;
int old_val = 0;
int state = 0;
const char* ckpd_one_cmd = "AT+CKPD=1,0,0";
rcode = Acm.SndData( strlen( ckpd_one_cmd ), (uint8_t *)ckpd_one_cmd );
class ACMAsyncOper : public CDCAsyncOper
{
public:
virtual uint8_t OnInit(ACM *pacm);
};
uint8_t ACMAsyncOper::OnInit(ACM *pacm)
{
uint8_t rcode;
// Set DTR = 1 RTS=1
rcode = pacm->SetControlLineState(3);
if (rcode)
{
ErrorMessage(PSTR("SetControlLineState"), rcode);
return rcode;
}
LINE_CODING lc;
lc.dwDTERate = 115200;
lc.bCharFormat = 0;
lc.bParityType = 0;
lc.bDataBits = 8;
rcode = pacm->SetLineCoding(&lc);
if (rcode)
ErrorMessage(PSTR("SetLineCoding"), rcode);
return rcode;
}
USB Usb;
//USBHub Hub(&Usb);
ACMAsyncOper AsyncOper;
ACM Acm(&Usb, &AsyncOper);
void setup()
{
Serial.begin( 115200 );
Serial.println("Start");
if (Usb.Init() == -1)
Serial.println("OSCOKIRQ failed to assert");
delay( 200 );
pinMode(BUTTON, INPUT);
}
void loop()
{
Usb.Task();
if( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
uint8_t rcode;
/* reading the keyboard */
if(Serial.available()) {
uint8_t data= Serial.read();
/* sending to the phone */
rcode = Acm.SndData(1, &data);
if (rcode)
ErrorMessage(PSTR("SndData"), rcode);
}//if(Serial.available()...
delay(50);
/* reading the phone */
/* buffer size must be greater or equal to max.packet size */
/* it it set to 64 (largest possible max.packet size) here, can be tuned down
for particular endpoint */
uint8_t buf[64];
uint16_t rcvd = 64;
rcode = Acm.RcvData(&rcvd, buf);
if (rcode && rcode != hrNAK)
ErrorMessage(PSTR("Ret"), rcode);
if( rcvd ) { //more than zero bytes received
for(uint16_t i=0; i < rcvd; i++ ) {
Serial.print(buf[i]); //printing on the screen
}
}
delay(10);
}//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..
{ val = digitalRead(BUTTON);
if ((val == HIGH) && (old_val == LOW))
{
state = 1;
}
else
{
state = 0;
}
if (state == 1) { ); // Here is where I press the button
}
}
}
you need to declare a class before using it.
Always the replies are vague . Never a direct answer .Read all the rest of his blogs . He wishes to feel important by making everyone chase him for answers. It is pointless to set up such a site and then avoid direct answers .
What does he gain by this ?
Notoriety?
oleg, i am working on a project where I can control a cell phone solely from the arduino using AT commands. I was wondering if you could give me a simple sample code of how to send an AT command to the phone. From the sample sketches i looked through it seems like Acm.SndData is a command to send data to the phone. Is this correct? If i wanted to send an AT command, what would the arduino sketch look like?
Just replace strings that I send with strings you need to send.
i am just unsure of the syntax of the acm.senddata fxn and what it returns
also, if im reading all of this correctly, in order for the usb shield to communicate with the cell phone it first needs to recognize the phone? You can’t just simply write a sketch that has the acm.senddata command and expect the phone to respond, correct?
ACM::Init() detects the device, not necessarily the phone. For example, it will also recognize 16U2-based USB-to-serial converter used in newer Arduinos. Init() is called from Usb, you don’t need to worry about it, just declare an instance of ACM class in your sketch, like I do. I also suggest studying the source code of ACM class -> https://github.com/felis/USB_Host_Shield_2.0/blob/master/cdcacm.cpp, you will find answer to your previous question there as well.
Mark, have you been able to get this to work? In Oleg’s reply to you he states “Just replace strings that I send with strings you need to send.” I’ve tried replacing ‘data’ in the line rcode = Acm.SndData(1, &data); with various characters, strings, decimal numbers to no avail. I am getting error messages that ultiamtely reflect to uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr)in the ACM class. Have you had any success? – Scotty
Mark, Oleg, this is the code that worked for me. :
#include
#include
#include “pgmstrings.h”
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include
#endif
class ACMAsyncOper :
public CDCAsyncOper
{
public:
virtual uint8_t OnInit(ACM *pacm);
};
uint8_t ACMAsyncOper::OnInit(ACM *pacm)
{
uint8_t rcode;
// Set DTR = 1 RTS=1
rcode = pacm->SetControlLineState(3);
if (rcode)
{
ErrorMessage(PSTR(“SetControlLineState”), rcode);
return rcode;
}
LINE_CODING lc;
lc.dwDTERate = 115200;
lc.bCharFormat = 0;
lc.bParityType = 0;
lc.bDataBits = 8;
rcode = pacm->SetLineCoding(&lc);
if (rcode)
ErrorMessage(PSTR(“SetLineCoding”), rcode);
return rcode;
}
USB Usb;
//USBHub Hub(&Usb);
ACMAsyncOper AsyncOper;
ACM Acm(&Usb, &AsyncOper);
boolean done = false; //flag to ensure message only sent once
uint8_t rcode;
char mode[] = “AT+CMGF=1\r”;//used to put phone into text mode
int modelen = strlen(mode);
char phone[] = “AT+CMGS=\”+16105551212\”\r”; //phone number to text to
int phonelen = strlen(phone);
char message[] = “From Razr!”; //message to be sent
int messagelen = strlen(message);
byte ctrlz = 26; //send message
void setup()
{
Serial.begin( 115200 );
while (!Serial); // Wait for serial port to connect – used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
Serial.println(“Start”);
if (Usb.Init() == -1)
Serial.println(“OSCOKIRQ failed to assert”);
delay( 200 );
}
void loop()
{
Usb.Task();
if( Acm.isReady()) {
//uint8_t rcode;
/* sending to the phone */
if (done==false){//if true, prevents multiple messages from being sent
Mode_Setup();//used to put phone into text mode
delay(100);
Read_Function();
delay(100);
Enter_Number(); //used to enter phone number to be texted to
delay(100);
Read_Function();
delay(100);
Message(); // used to enter message to be sent
delay(100);
Read_Function();
delay(100);
Send_Ctrlz(); //used to signal ‘send message’
delay(100);
Read_Function();
delay(100);
}
if (rcode)
ErrorMessage(PSTR(“SndData”), rcode);
done = true;
}
delay(50);
}//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..
int Mode_Setup(){
for (int i = 0; i < modelen; i++){
uint8_t data = mode[i];
rcode = Acm.SndData(1, &data);
}
//Serial.println(" Mode Setup Complete");
}
int Enter_Number(){
for (int i = 0; i < phonelen; i++){
uint8_t data = phone[i];
rcode = Acm.SndData(1, &data);
delay(50);
}
//Serial.println(" Enter Number Complete");
}
int Message(){
for (int i = 0; i < messagelen; i++){
uint8_t data = message[i];
rcode = Acm.SndData(1, &data);
}
//Serial.println(" Send Message Complete");
}
int Send_Ctrlz(){
uint8_t data = ctrlz;
rcode = Acm.SndData(1, &data);
//Serial.println(" Send Ctrlz Complete");
}
int Read_Function(){
/* reading the phone */
/* buffer size must be greater or equal to max.packet size */
/* it it set to 64 (largest possible max.packet size) here, can be tuned down
for particular endpoint */
//Serial.println ("In Read Function");
uint8_t buf[64];
uint16_t rcvd = 64;
rcode = Acm.RcvData(&rcvd, buf);
if (rcode && rcode != hrNAK)
ErrorMessage(PSTR(“Ret”), rcode);
if( rcvd ) { //more than zero bytes received
for(uint16_t i=0; i < rcvd; i++ ) {
Serial.print((char)buf[i]); //printing on the screen
}
}
delay(10);
}
Good job!
Thanks for the help
to send AT commands to a cell phone, could you not just use the SPI interface and library provided on the arduino website?
good day ..
can i ask a question ..as what I’ve seen ..theirs two usb cable ,black and white,I wonder where’s the black cable goes..then does mean.
looking forward for your response..
taz
Black cable goes to a PC.
good day to all..
.. this article is very interesting ..can I ask for a question..
as what i’ve seen there are two usb cable wire.white and black..
I wonder were the black cable goes.??..and what is its function
looking forward for your respond..
thank u