Rasberry Pi Pico saves data in multiple txt files when connected to an external power source - save

I have a temperature sensor connected to rasberry pi pico and have a main.py, which records the temperature data into .txt file. When I connect the rasberry pi to PC via USB port, it starts recording and saves the data in one .txt file. However, when I connect it to an external power supply (AC DC adapter with output 5V), the data is saved in multiple .txt files of different sizes (named logfile_0001.txt, logfile_0002.txt, ... as expected).
Main.py starts running whenever the rasberry pi is connected to the external power supply, and I can confirm that by the LED, which I programmed it to blink when it starts collecting data and after writing the first three lines.
The weird thing is, I never observe LED blinking more than the initial blink right when it is connected to the external power, even though it should whenever it writes the three header lines. Each separate txt file does contain those three lines as headers. I am very confused how the file can have the three lines without LED blinking, too.
Here is the code after setting up the i2c using machine module in micropython:
#naming the file
num = 0
for file in os.ilistdir():
file_name = file[0]
if not file[0].startswith('logfile'):
continue
temp = int(file_name[8:13])
if temp > num:
num = temp
num += 1
file_name = f'logfile_{num:05d}.txt'
with open(file_name,'w') as f:
f.write('Humidity and temperature data taken using T9602 Humidity & Temperature Sensor, on Rasberry Pi Pico\n')
f.write(str(time.localtime(start_time)) +'\n')
f.write('unixTime Humidity1(%) Temperature1(C) Humidity2(%) Temperature2(C)\n')
#LED blinks when connected
if True:
led_onboard.value(1)
for i in range(3):
led_onboard.value(0)
utime.sleep(0.3)
led_onboard.value(1)
utime.sleep(0.3)
led_onboard.value(0)
while True:
#turn on LED when recording data
led_onboard.value(1)
#communicate with two i2c devices (sensors)
i2c.writeto(address[0],b'1')
i2c2.writeto(address2[0],b'1')
#calculating temperatures based on the data read
RH1, TH1 = data_calc(i2c.readfrom(address[0],4))
with open(file_name, 'a') as f:
f.write(f'{time.time()} {RH1} {TH1} {RH2} {TH2}\n')
print(f'{time.localtime(time.time())[:-2]} {RH1} {TH1} {RH2} {TH2}')
time.sleep(1)
If someone have any insights, I would greatly appreciate it! Thank you so much.

Related

pyserial issues with high baudrate FTDI

I have the following setup:
A FPGA sending out data on UART at a baudrate of 3Mbps. The data transmitted is a chunk of 1024 bytes sent at a variable periodicity ranging from 20ms to 200ms. (So even in the worst case, datarate is far from 3Msps)
A FTDI 232RG
A piece of python running on my computer (Windows), doing basically : opening a COM port with pyserial, 3Msps, polling the in_waiting until it reaches the size of a packet (1024 bytes), formatting the packet received and print it on the screen
The script works well for low repetition frequency, but I face issues with higher repetitions (typically 20ms). When the periodicity in 20ms I eventually end up getting a buffer overflow somewhere before the in_waiting. I checked the timing of my python loop and it takes about 4ms. So it looks like there is something upstream (in the FTDI or Windows) that feeds the pyserial buffer with more than one packet within the 4ms following a packet.
I tried changing the FTDI latency in the driver (from 16ms default down to a few ms) but it does not seem to help.
I am currently clueless about what is happening. Would you have any advice about how to understand better what is happening?
Thanks for your help!
You could create a "loop" between TX and RX and run the following code (tested with a FT2232H, so mostlikely you need to change the identifier string):
import time
import serial
import serial.tools.list_ports
print([(x[0],x[2]) for x in serial.tools.list_ports.comports()])
port = [x[0] for x in serial.tools.list_ports.comports() if "FT4Q1LJFB" in x[2]][0]
ser = serial.Serial(port,12000000)
while True:
t0 = time.time()
counter = 0
for i in range(1000):
ser.write([1]*3000)
recv = ser.read(ser.inWaiting())
delta_t = time.time() - t0
counter += len(recv)
print(counter / delta_t)
For me the following output is shown
[('COM7', 'USB VID:PID=0403:6010 SER=FT4Q1LJFA'), ('COM8', 'USB VID:PID=0403:6010 SER=FT4Q1LJFB')]
0.0
0.0
0.0
0.0
96787.81184093593
1201991.0268273412
1201197.0857713912
1201166.9350959768
1201445.4072856384
You will notice that it is 0.0 in the beginning. This is because I connected RX and TX after starting the program resulting in a ramping up of the received bytes. This is the "default" mode meaning 8 bits + 1 start bit + 1 stop bit = 10 bits per word which explains why "only" 1.2 Mbytes per second are transmitted.

Flashing ESP8266 with a LittleFS binary

I'm trying to build a LittleFS file system binary on my PC and flash it to my WeMos D1 Mini Pro (16MB) ESP8266.
I used the following code on the ESP
LittleFS.begin()
FSInfo info;
LittleFS.info(info);
Serial.print("LittleFS block size:");
Serial.println(info.blockSize);
Serial.print("LittleFS total bytes:");
Serial.println(info.totalBytes);
To determine the block size and total bytes, which gave me 8192 and 14655488 respectively. 14655488 / 8192 = 1789 so I used 1789 as the block size in the below python:
from littlefs import LittleFS
fs = LittleFS(block_size=8192, block_count=1789)
with open( 'index.html', 'rb' ) as f:
data = f.read()
with fs.open( '/index.html', 'w') as fh:
fh.write( data )
with open('fs.bin', 'wb') as fh:
fh.write(fs.context.buffer)
This creates a 14655488 bytes .bin file.
I then looked in boards.txt and found these lines:
d1_mini_pro.menu.eesz.16M14M=16MB (FS:14MB OTA:~1019KB)
d1_mini_pro.menu.eesz.16M14M.build.flash_size=16M
d1_mini_pro.menu.eesz.16M14M.build.flash_size_bytes=0x1000000
d1_mini_pro.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld
d1_mini_pro.menu.eesz.16M14M.build.spiffs_pagesize=256
d1_mini_pro.menu.eesz.16M14M.upload.maximum_size=1044464
d1_mini_pro.menu.eesz.16M14M.build.rfcal_addr=0xFFC000
d1_mini_pro.menu.eesz.16M14M.build.spiffs_start=0x200000
d1_mini_pro.menu.eesz.16M14M.build.spiffs_end=0xFFA000
d1_mini_pro.menu.eesz.16M14M.build.spiffs_blocksize=8192
This confirms the block size and gives the SPIFFS (but LittleFS is equivalent here, right?) start address as 0x200000
Checking these Arduino bits, i get:
FS_PHYS_ADDR: 2097152 (0x200000)
FS_PHYS_SIZE: 14655488
FS_PHYS_PAGE: 256
FS_PHYS_BLOCK: 8192
So then I used:
python upload.py --chip esp8266 --port COM6 --baud 460800 write_flash 0x200000 fs.bin
which outputs:
esptool.py v2.8
Serial port COM6
Connecting....
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: ec:fa:bc:6e:19:90
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Auto-detected Flash size: 16MB
Compressed 14655488 bytes to 215596...
Writing at 0x00234000... (100 %)
Wrote 14655488 bytes (215596 compressed) at 0x00200000 in 56.7 seconds (effective 2067.0 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
However, when I then use code like the below
Dir root = LittleFS.openDir("/");
while (root.next())
{
Serial.print(root.fileName());
}
I get nothing, and
LittleFS.exists("/index.html")
returns false.
What am I doing wrong, or how do I debug this?
I'm uploading my firmware (not the filesystem) via Visual Studio Code, and the board configuration I'm using is
"xtal=80,vt=flash,exception=legacy,ssl=all,eesz=16M14M,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=921600"
If I open the bin in a hex editor, I can see:
Which is some javascript inside the html file.
If I do this:
uint32_t b;
ESP.flashRead(0x006C2800 + 0x200000, &b, 1);
Serial.println(b);
then it returns 115/0x73, so it looks like the binary has flashed successfully, so that leaves me with either the binary being flashed in the wrong place, or it being corrupted/invalid....
I haven't fixed this exact problem, but I have achieved what I want.
This:
C:\Users\Andrew Bullock\AppData\Local\Arduino15\packages\esp8266\tools\mklittlefs\2.5.0-4-fe5bb56\mklittlefs.exe
exists (instructions here https://github.com/earlephilhower/mklittlefs) which works. So I can only assume that the Python wrapper or the version of LittleFS it's using is somehow incompatible or broken.
The only problem here i can see is that the block_count you gave in your python script is wrong. block_count actually refers to the pageSize of the Filesystem, that holds number of bytes every page is going to hold, in ESP littleFS the pageSize is 256.
So your object initialisation should be like this:
fs = LittleFS(block_size=8192, block_count=259)

Distingushing between multiple cameras using OpenCV

I'm trying to run a usb camera (webcam) and a leap-motion 'camera' under OpenCV
code:
cv:VideoCapture st0 = cv:VideoCapture();
cv:VideoCapture st1 = cv:VideoCapture();
isOpen0 = st0.open(0);
isOpen1 = st1.open(1);
Problem is that each time the program loads the webcam and leap-motion gets different indexes and I could not find a place where I can get info on the cameras like a description string, serial number, manufacturer or any other parameter that can help me distinguish between the two.

Printting on dot matrix printer with only Tx, Rx and Ground

My hardware communicate with PC serial port using Tx, Rx and ground lines for sending and receiving data, I wrote a program which can send some text to PC via serial line, now I wanted to alter it in such a way that I should be able to print that data on dot matrix printer which has a serial port.
I am using an Epson LQ 1150 dot matrix printer which has a db25 serial port. I tried connecting in following manner and sent data over serial line, the printer prints some garbage character and hangs.
Tx = Rx
Rx = Tx
Ground = Ground
I tried searching other posts explaining(db9-M to db25-F) :
Receive Data (RxD) 2 = 2 Transmit Data (TxD)
Transmit Data (TxD) 3 = 3 Receive Data (RxD)
Data Terminal Ready (DTR) 4 = 6 Data Set Ready (DSR)
System Ground (SG) 5 = 7 System Ground (SG)
Data Set Ready (DSR) 6 = 20 Data Terminal Ready (DTR)
Clear To Send (CTS) 8 = 4 Request To Send (RTS)
But I don't have DTR, DSR,and CTS. Is there any way I can make it possible using only 3 lines i.e. Tx, Rr and ground?

Detect SSD using Delphi [duplicate]

I'm getting ready to release a tool that is only effective with regular hard drives, not SSD (solid state drive). In fact, it shouldn't be used with SSD's because it will result in a lot of read/writes with no real effectiveness.
Anyone knows of a way of detecting if a given drive is solid-state?
Finally a reliable solution! Two of them, actually!
Check /sys/block/sdX/queue/rotational, where sdX is the drive name. If it's 0, you're dealing with an SSD, and 1 means plain old HDD.
I can't put my finger on the Linux version where it was introduced, but it's present in Ubuntu's Linux 3.2 and in vanilla Linux 3.6 and not present in vanilla 2.6.38. Oracle also backported it to their Unbreakable Enterprise kernel 5.5, which is based on 2.6.32.
There's also an ioctl to check if the drive is rotational since Linux 3.3, introduced by this commit. Using sysfs is usually more convenient, though.
You can actually fairly easily determine the rotational latency -- I did this once as part of a university project. It is described in this report. You'll want to skip to page 7 where you see some nice graphs of the latency. It goes from about 9.3 ms to 1.1 ms -- a drop of 8.2 ms. That corresponds directly to 60 s / 8.2 ms = 7317 RPM.
It was done with simple C code -- here's the part that measures the between positions aand b in a scratch file. We did this with larger and larger b values until we have been wandered all the way around a cylinder:
/* Measure the difference in access time between a and b. The result
* is measured in nanoseconds. */
int measure_latency(off_t a, off_t b) {
cycles_t ta, tb;
overflow_disk_buffer();
lseek(work_file, a, SEEK_SET);
read(work_file, buf, KiB/2);
ta = get_cycles();
lseek(work_file, b, SEEK_SET);
read(work_file, buf, KiB/2);
tb = get_cycles();
int diff = (tb - ta)/cycles_per_ns;
fprintf(stderr, "%i KiB to %i KiB: %i nsec\n", a / KiB, b / KiB, diff);
return diff;
}
This command lsblk -d -o name,rota lists your drives and has a 1 at ROTA if it's a rotational disk and a 0 if it's an SSD.
Example output :
NAME ROTA
sda 1
sdb 0
Detecting SSDs is not as impossible as dseifert makes out. There is already some progress in linux's libata (http://linux.derkeiler.com/Mailing-Lists/Kernel/2009-04/msg03625.html), though it doesn't seem user-ready yet.
And I definitely understand why this needs to be done. It's basically the difference between a linked list and an array. Defragmentation and such is usually counter-productive on a SSD.
You could get lucky by running
smartctl -i sda
from Smartmontools. Almost all SSDs has SSD in the Model field. No guarantee though.
My two cents to answering this old but very important question... If a disk is accessed via SCSI, then you will (potentially) be able to use SCSI INQUIRY command to request its rotational rate. VPD (Vital Product Data) page for that is called Block Device Characteristics and has a number 0xB1. Bytes 4 and 5 of this page contain a number with meaning:
0000h "Medium rotation rate is not reported"
0001h "Non-rotating medium (e.g., solid state)"
0002h - 0400h "Reserved"
0401h - FFFEh "Nominal medium rotation rate in rotations per minute (i.e.,
rpm) (e.g., 7 200 rpm = 1C20h, 10 000 rpm = 2710h, and 15 000 rpm = 3A98h)"
FFFFh "Reserved"
So, SSD must have 0001h in this field. The T10.org document about this page can be found here.
However, the implementation status of this standard is not clear to me.
I wrote the following javascript code. I needed to determine if machine was ussing SSD drive and if it was boot drive. The solution uses MSFT_PhysicalDisk WMI interface.
function main()
{
var retval= false;
// MediaType - 0 Unknown, 3 HDD, 4 SSD
// SpindleSpeed - -1 has rotational speed, 0 has no rotational speed (SSD)
// DeviceID - 0 boot device
var objWMIService = GetObject("winmgmts:\\\\.\\root\\Microsoft\\Windows\\Storage");
var colItems = objWMIService.ExecQuery("select * from MSFT_PhysicalDisk");
var enumItems = new Enumerator(colItems);
for (; !enumItems.atEnd(); enumItems.moveNext())
{
var objItem = enumItems.item();
if (objItem.MediaType == 4 && objItem.SpindleSpeed == 0)
{
if (objItem.DeviceID ==0)
{
retval=true;
}
}
}
if (retval)
{
WScript.Echo("You have SSD Drive and it is your boot drive.");
}
else
{
WScript.Echo("You do not have SSD Drive");
}
return retval;
}
main();
SSD devices emulate a hard disk device interface, so they can just be used like hard disks. This also means that there is no general way to detect what they are.
You probably could use some characteristics of the drive (latency, speed, size), though this won't be accurate for all drives. Another possibility may be to look at the S.M.A.R.T. data and see whether you can determine the type of disk through this (by model name, certain values), however unless you keep a database of all drives out there, this is not gonna be 100% accurate either.
write text file
read text file
repeat 10000 times...
10000/elapsed
for an ssd will be much higher, python3:
def ssd_test():
doc = 'ssd_test.txt'
start = time.time()
for i in range(10000):
with open(doc, 'w+') as f:
f.write('ssd test')
f.close()
with open(doc, 'r') as f:
ret = f.read()
f.close()
stop = time.time()
elapsed = stop - start
ios = int(10000/elapsed)
hd = 'HDD'
if ios > 6000: # ssd>8000; hdd <4000
hd = 'SSD'
print('detecting hard drive type by read/write speed')
print('ios', ios, 'hard drive type', hd)
return hd

Resources