
15 Mar
2025
15 Mar
'25
2:32 p.m.
karl3@writeme.com wrote: > > > > so, sending robots into [air]space first lets them accumulate supplies for you there until you move there yourself. > > > > > thinking for a final product you'd want 2-3 ways to connect to it remotely (and get gps) in case it is high in the sky and one of them breaks. > > > > > so, things i could buy today to make a barebones prototype today: > > > > - power pack (ideally a solar one) to power arduino and motors > > > > - power adapter for motors? > > > > - party balloons > > > > - twine, construction materials > > > > i'm spending time working on setting up an SOC. my current chosen approach is my cellphone wired to an arduino with termux running tmate on boot. > > > > this approach roughly means patching avrdude to accept a filedescriptor on the command line so as to connect to the arduino via android. i'm working on that now. > > > > tmate lets other people watch you; the login for that would be karl3wm/connect@nyc1.tmate.io or something like that > > > > the example code for patches to access usb devices on termux is at https://wiki.termux.com/wiki/Termux-usb#Details > > well the avrdude code is based on libusb 0.1 whereas termux has 1.0 and it's pretty slow to code over tmate.io on a phone; i think it makes more sense to program the arduino elsewhere and use a serial interface to preprogrammed code on the phone for now. > > There's an example in c and python for serially interfacing with arduinos via libusb at https://github.com/tytouf/libusb-cdc-example . > > so that's the essentials :s :s :s > > i think it makes sense to acquire a power supply next to make the motors run, but i'll slow down now we'll see how it goes. > > a day trip today for this might involve: > - visit cricket and put a data plan on this phone, or get a phone anywhere > - get a power pack (ideally solar) to run everything > - get bare wiring for the power pack sufficient to power a motor > - get general hobby wiring and wire cutters and optionally a soldering tool > - get party balloons > - get some prototype construction materials, umm i guess: twine, duct tape, hot glue, some rods > - get hobby wiring and optional soldering tool > > now, i have a toy fan and a servo gimbal. this might not be sufficient to move something around in the air :s continued work seems presently conditioned a functioning result :s :s i've got my phone controlling a servo from the gimbal via ssh ! I think this is the sketch I put on the arduino: https://projecthub.arduino.cc/Kub_Luk/using-serial-monitor-to-control-servo-motor-c55083#section5 Of course arduino sketches are silly and I would prefer a makefile but there is less normativity and clear instructions to navigate confusion. I put the red wire into 5VDC, the dark wire into GND, and the yellow wire into pin 9. This is the first time I've ever controlled a motor with a phone as far as I know! My changed cdc_example.c is viewable at https://bpa.st/654Q . The diff is at https://bpa.st/WRAA and pasted below: diff --git a/cdc_example.c b/cdc_example.c index fd21e23..e6a35e8 100644 --- a/cdc_example.c +++ b/cdc_example.c @@ -11,12 +11,6 @@ #include <libusb-1.0/libusb.h> -/* You may want to change the VENDOR_ID and PRODUCT_ID - * depending on your device. - */ -#define VENDOR_ID 0x2341 // Arduino LLC -#define PRODUCT_ID 0x0034 // Arduino Leonardo - #define ACM_CTRL_DTR 0x01 #define ACM_CTRL_RTS 0x02 @@ -28,18 +22,21 @@ static struct libusb_device_handle *devh = NULL; * the values corresponding to your device. */ static int ep_in_addr = 0x83; -static int ep_out_addr = 0x02; +static int ep_out_addr = 0x04; // UNO -void write_char(unsigned char c) +int write_char(unsigned char c) { /* To send a char to the device simply initiate a bulk_transfer to the * Endpoint with address ep_out_addr. */ int actual_length; - if (libusb_bulk_transfer(devh, ep_out_addr, &c, 1, - &actual_length, 0) < 0) { - fprintf(stderr, "Error while sending char\n"); + int rc; + if ((rc = libusb_bulk_transfer(devh, ep_out_addr, &c, 1, + &actual_length, 0)) < 0) { + fprintf(stderr, "Error while sending char: %s\n", libusb_error_name(rc)); + return -1; } + return 0; } int read_chars(unsigned char * data, int size) @@ -51,10 +48,10 @@ int read_chars(unsigned char * data, int size) int rc = libusb_bulk_transfer(devh, ep_in_addr, data, size, &actual_length, 1000); if (rc == LIBUSB_ERROR_TIMEOUT) { - printf("timeout (%d)\n", actual_length); - return -1; + //printf("timeout (%d)\n", actual_length); + return 0; } else if (rc < 0) { - fprintf(stderr, "Error while waiting for char\n"); + fprintf(stderr, "Error while waiting for char: %s\n", libusb_error_name(rc)); return -1; } @@ -63,13 +60,11 @@ int read_chars(unsigned char * data, int size) int main(int argc, char **argv) { + libusb_context * ctx; int rc; - /* Initialize libusb - */ - rc = libusb_init(NULL); - if (rc < 0) { - fprintf(stderr, "Error initializing libusb: %s\n", libusb_error_name(rc)); + if (argc != 2) { + fprintf(stderr, "Usage: termux-usb -e %s /dev/bus/usb/00?/00?\n", argv[0]); exit(1); } @@ -77,20 +72,29 @@ int main(int argc, char **argv) */ libusb_set_debug(NULL, 3); - /* Look for a specific device and open it. + /* Initialize libusb */ - devh = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID); - if (!devh) { - fprintf(stderr, "Error finding USB device\n"); - goto out; + libusb_set_option(NULL, LIBUSB_OPTION_NO_DEVICE_DISCOVERY); + rc = libusb_init(&ctx); + if (rc < 0) { + fprintf(stderr, "Error initializing libusb: %s\n", libusb_error_name(rc)); + exit(1); } - /* As we are dealing with a CDC-ACM device, it's highly probable that - * Linux already attached the cdc-acm driver to this device. - * We need to detach the drivers from all the USB interfaces. The CDC-ACM - * Class defines two interfaces: the Control interface and the - * Data interface. + /* Look for a specific device and open it. */ + int fd; + rc = sscanf(argv[1], "%d", &fd); + if (rc != 1) { + fprintf(stderr, "Failed to read fd: %d\n", rc); + exit(1); + } + rc = libusb_wrap_sys_device(ctx, (intptr_t) fd, &devh); + if (rc != 0) { + fprintf(stderr, "Failed to wrap fd %d: %s\n", fd, libusb_error_name(rc)); + exit(1); + } + for (int if_num = 0; if_num < 2; if_num++) { if (libusb_kernel_driver_active(devh, if_num)) { libusb_detach_kernel_driver(devh, if_num); @@ -111,6 +115,7 @@ int main(int argc, char **argv) if (rc < 0) { fprintf(stderr, "Error during control transfer: %s\n", libusb_error_name(rc)); + goto out; } /* - set line encoding: here 9600 8N1 @@ -122,19 +127,34 @@ int main(int argc, char **argv) if (rc < 0) { fprintf(stderr, "Error during control transfer: %s\n", libusb_error_name(rc)); + goto out; } /* We can now start sending or receiving data to the device */ unsigned char buf[65]; - int len; - + int len, inputlen; + + fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK); + + fprintf(stderr, "Connected.\n"); + while(1) { - write_char('t'); + while ((inputlen = read(0, buf, 1)) == 1) { + if (write_char(buf[0])) { + break; + } + } + if (inputlen < 0 && errno != EAGAIN) { + perror("read"); + break; + } len = read_chars(buf, 64); + if (len == -1) { fprintf(stderr, "failed read chars\n"); break; } + if (len == 0) { usleep(150000); continue; } buf[len] = 0; - fprintf(stdout, "Received: \"%s\"\n", buf); - sleep(1); + fprintf(stdout, "%s", buf); + fflush(stdout); } libusb_release_interface(devh, 0); @@ -142,6 +162,6 @@ int main(int argc, char **argv) out: if (devh) libusb_close(devh); - libusb_exit(NULL); + libusb_exit(ctx); return rc; }