Выбор МК/контроллера для чтения файла с USB Flash Drive

Задумали тут с коллегой железку в помощь сельхоз производителю, логика работы банальная, но встал вопрос переноса пропорций/рецептуры взвешиваемых кормов/компонентов из компьютера в данную железку.
Т е идет работник в офис, получает от девочки/менеджера флэшку, вставляет ее в устройство, железка записала себе рецептуру, начала работать.

Вопрос: есть ли какой либо контроллер (относительно дешевый), который без проблем понимает флэшки и позволяет с нее читать файлы?

У меня только мысль про Orange PI.

Я предложил ему WiFi/Bluetooth, но для них (работников) это будет очень сложно забивать данные непосредственно в устройство.

Любой контроллер с usb хостом, в чем проблема-то.
rp2040, esp32s2, blue pill

хм…не знал, пошел читать есть в SDK пример работы.

Главное - чтобы там NTFS не было или рецепты не скидывались как .lnk

ну не, под ВИнду тоже программу придется писать, т е в GUI юзер выбирает что нужно и сколько, и прога какой нибудь текстовый файл с параметрами сама будет на флэшку писать.

Не нашёл я примеров подключения флэшки к МК, в основном эмуляции usb hid устройств :frowning:
Сам не осилю, сложно.
Наверное буду на Orange pi делать, там в Linux уже все и так есть.
Или через sd карту делать перенос настроек с пк на МК.

А этот оранже сильно греется? Я тут смотрел модельный ряд, хотел чтобы мелконький и с системой в NAND и памяти штоп не как в 328-м… Но на форумах пишут, что по скорости цпу все завышено, перегревается. Или ставь кулер или занижай клок… Вобщем, опять урок труда с китайской заготовкой. Больше раскочегариваешь систему, чем едешь.

Хлам. Для самоделок не годится.

Orange pi даже на серийные устройства вполне идут, во всяком случае один реальный проект под него я писал. И он сильно дешевле малинки, что является сильным фактором.
Греется да, знатно. Лечится установкой пары мелких радиаторов и одного кулера.

не в тему форума, но вдруг кому понадобиться
вставляемая в orange PI флэшка монтируется самостоятельно в /mnt/usb
требуется библиотека
apt-get install libudev-dev

Спойлер
// tznusb.c

#include <pthread.h>
#include <stdio.h>
#include "tznusb.h"
#include <unistd.h>
#include <libudev.h>
#include <string.h>
#include <sys/mount.h>
#include <errno.h>

char tznLinkUsbDrive[16];
void (*callbackUSBresp)(int);

void tznUSBsetCallback(void (*inCallbackUSB)(int)) {
	callbackUSBresp = inCallbackUSB;
}

int tznMount(void) {
	int flagGood = 0;
	char startPath[] = "/dev/sda1";
	for(char setChar = 'a'; setChar <= 'z'; ++setChar) {
		startPath[7] = setChar;
		int ret = mount(startPath, tzn_mount_usb_path, "vfat", MS_NOATIME | MS_RDONLY, NULL);
		if(ret == 0) {
			printf("Mounting %s success\n", startPath);
			tznLinkUsbDrive[0] = '\0';
			strcpy(tznLinkUsbDrive, startPath);
			flagGood = 1;
			break;
		} else {
            printf("Mounting %s %s\n",startPath, strerror(errno));
		}
	}
	if (flagGood == 1) return 0; else return -1;
}

void *tznUSBthread(void * param) { // потоковая функция USB
	printf("Start tznUSBthread\n");
	struct udev *udev;
	struct udev_device *dev;
   	struct udev_monitor *mon;
	int fd;
	char devMan[128];
	char devProd[128];
	devMan[0] = '\0';
	devProd[0] = '\0';
	udev = udev_new(); // create udev object
	if (!udev) {
		fprintf(stderr, "Can't create udev\n");
		pthread_exit(0);
	}
	mon = udev_monitor_new_from_netlink(udev, "udev");
	udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", NULL);
	udev_monitor_enable_receiving(mon);
	fd = udev_monitor_get_fd(mon);
	while (1) {
		fd_set fds;
		struct timeval tv;
		int ret;
		FD_ZERO(&fds);
		FD_SET(fd, &fds);
		tv.tv_sec = 0;
		tv.tv_usec = 0;
		static int flagUsbInterface = 0;
		ret = select(fd+1, &fds, NULL, NULL, &tv);
		if (ret > 0 && FD_ISSET(fd, &fds)) {
			dev = udev_monitor_receive_device(mon);
			if (dev) {
				if (strcmp(udev_device_get_action(dev), "add") == 0) {
					if (strcmp(udev_device_get_devtype(dev), "usb_device") == 0) {
						flagUsbInterface = 1;
						strcpy(devMan, udev_device_get_sysattr_value(dev,"manufacturer"));
						strcpy(devProd, udev_device_get_sysattr_value(dev,"product"));
						callbackUSBresp(respUSBinsert);
					} else if ((strcmp(udev_device_get_devtype(dev), "usb_interface") == 0) && (flagUsbInterface == 1)) {
						flagUsbInterface = 0;
						usleep(1000*1000); // 1000 milliseconds 
						printf("  %s\n  %s\n",
							devMan,	devProd);
						if (tznMount() == 0) callbackUSBresp(respUSBmounted); else callbackUSBresp(respUSBerror);
					} else {
						flagUsbInterface = 0;
						devMan[0] = '\0';
						devProd[0] = '\0';
					}
				} else if (strcmp(udev_device_get_action(dev), "remove") == 0) {
					if (strcmp(udev_device_get_devtype(dev), "usb_device") == 0) {
						devMan[0] = '\0';
						devProd[0] = '\0';
						callbackUSBresp(respUSBleave);
					}
				}
				udev_device_unref(dev); // free dev
			}
		}
		usleep(500*1000); // 500 milliseconds 
		pthread_testcancel();
	}
	udev_unref(udev); // free udev
	pthread_exit(0);
}