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;
}