I am taking a course on Cryptography and am stuck on an assignment. The instructions are as follows:
The plaintext plain6.txt has been encrypted with DES to encrypt6.dat using a 64-bit key given as a string of 8 characters (64
bits of which every 8th bit is ignored), all characters being letters
(lower-case or upper-case) and digits (0 to 9).
To complete the assignment, send me the encryption key before February
12, 23.59.
Note: I expect to get an 8-byte (64-bits) key. Each byte should
coincide with the corresponding byte in my key, except for the least
significant bit which is not used in DES and thus, could be arbitrary.
Here is the code to my first attempt in Python:
import time
from Crypto.Cipher import DES
class BreakDES(object):
def __init__(self, file, passwordLength = 8, testLength = 8):
self.file = file
self.passwordLength = passwordLength
self.testLength = testLength
self.EncryptedFile = open(file + '.des')
self.DecryptedFile = open(file + '.txt')
self.encryptedChunk = self.EncryptedFile.read(self.testLength)
self.decryptedChunk = self.DecryptedFile.read(self.testLength)
self.start = time.time()
self.counter = 0
self.chars = range(48, 58) + range(65, 91) + range(97, 123)
self.key = False
self.broken = False
self.testPasswords(passwordLength, 0, '')
if not self.broken:
print "Password not found."
duration = time.time() - self.start
print "Brute force took %.2f" % duration
print "Tested %.2f per second" % (self.counter / duration)
def decrypt(self):
des = DES.new(self.key.decode('hex'))
if des.decrypt(self.encryptedChunk) == self.decryptedChunk:
self.broken = True
print "Password found: 0x%s" % self.key
self.counter += 1
def testPasswords(self, width, position, baseString):
for char in self.chars:
if(not self.broken):
if position < width:
self.testPasswords(width, position + 1, baseString + "%c" % char)
self.key = (baseString + "%c" % char).encode('hex').zfill(16)
self.decrypt()
# run it for password length 4
BreakDES("test3", 4)
I am getting a speed of 60.000 tries / second. A password of 8 bytes over 62 characters gives 13 trillion possibilities, which means that at this speed it would take me 130 years to solve. I know that this is not an efficient implementation and that I could get better speeds in a faster language like C or it's flavors, but I have never programmed in those. Even if I get a speed-up of 10, we're still a huge leap away from 10,000,000,000 per second to get in the hours range.
What am I missing? This is supposed to be a weak key :). Well, weaker than the full 256 character set.
EDIT
Due to some ambiguity about the assignment, here is the full description and some test files for calibration: http://users.abo.fi/ipetre/crypto/assignment6.html
EDIT 2
This is a crude C implementation that gets around 2.000.000 passwords/s per core on an i7 2600K. You have to specify the first character of the password and can manually run multiple instances on different cores/computers. I managed to solve the problem using this within a couple of hours on four computers.
#include <stdio.h> /* fprintf */
#include <stdlib.h> /* malloc, free, exit */
#include <unistd.h>
#include <string.h> /* strerror */
#include <signal.h>
#include <openssl/des.h>
static long long unsigned nrkeys = 0; // performance counter
char *
Encrypt( char *Key, char *Msg, int size)
{
static char* Res;
free(Res);
int n=0;
DES_cblock Key2;
DES_key_schedule schedule;
Res = ( char * ) malloc( size );
/* Prepare the key for use with DES_ecb_encrypt */
memcpy( Key2, Key,8);
DES_set_odd_parity( &Key2 );
DES_set_key_checked( &Key2, &schedule );
/* Encryption occurs here */
DES_ecb_encrypt( ( unsigned char (*) [8] ) Msg, ( unsigned char (*) [8] ) Res,
&schedule, DES_ENCRYPT );
return (Res);
}
char *
Decrypt( char *Key, char *Msg, int size)
{
static char* Res;
free(Res);
int n=0;
DES_cblock Key2;
DES_key_schedule schedule;
Res = ( char * ) malloc( size );
/* Prepare the key for use with DES_ecb_encrypt */
memcpy( Key2, Key,8);
DES_set_odd_parity( &Key2 );
DES_set_key_checked( &Key2, &schedule );
/* Decryption occurs here */
DES_ecb_encrypt( ( unsigned char (*) [8]) Msg, ( unsigned char (*) [8]) Res,
&schedule, DES_DECRYPT );
return (Res);
}
void ex_program(int sig);
int main(int argc, char *argv[])
{
(void) signal(SIGINT, ex_program);
if ( argc != 4 ) /* argc should be 2 for correct execution */
{
printf( "Usage: %s ciphertext plaintext keyspace \n", argv[0] );
exit(1);
}
FILE *f, *g;
int counter, i, prime = 0, len = 8;
char cbuff[8], mbuff[8];
char letters[] = "02468ACEGIKMOQSUWYacegikmoqsuwy";
int nbletters = sizeof(letters)-1;
int entry[len];
char *password, *decrypted, *plain;
if(atoi(argv[3]) > nbletters-2) {
printf("The range must be between 0-%d\n", nbletters-2);
exit(1);
}
prime = atoi(argv[1])
// read first 8 bytes of the encrypted file
f = fopen(argv[1], "rb");
if(!f) {
printf("Unable to open the file\n");
return 1;
}
for (counter = 0; counter < 8; counter ++) cbuff[counter] = fgetc(f);
fclose(f);
// read first 8 bytes of the plaintext file
g = fopen(argv[2], "r");
if(!f) {
printf("Unable to open the file\n");
return 1;
}
for (counter = 0; counter < 8; counter ++) mbuff[counter] = fgetc(g);
fclose(g);
plain = malloc(8);
memcpy(plain, mbuff, 8);
// fill the keys
for(i=0 ; i<len ; i++) entry[i] = 0;
entry[len-1] = prime;
// loop until the length is reached
do {
password = malloc(8);
decrypted = malloc(8);
// build the pasword
for(i=0 ; i<len ; i++) password[i] = letters[entry[i]];
nrkeys++;
// end of range and notices
if(nrkeys % 10000000 == 0) {
printf("Current key: %s\n", password);
printf("End of range ");
for(i=0; i<len; i++) putchar(letters[lastKey[i]]);
putchar('\n');
}
// decrypt
memcpy(decrypted,Decrypt(password,cbuff,8), 8);
// compare the decrypted with the mbuff
// if they are equal, exit the loop, we have the password
if (strcmp(mbuff, decrypted) == 0)
{
printf("We've got it! The key is: %s\n", password);
printf("%lld keys searched\n", nrkeys);
exit(0);
}
free(password);
free(decrypted);
// spin up key until it overflows
for(i=0 ; i<len && ++entry[i] == nbletters; i++) entry[i] = 0;
} while(i<len);
return 0;
}
void ex_program(int sig) {
printf("\n\nProgram terminated %lld keys searched.\n", nrkeys);
(void) signal(SIGINT, SIG_DFL);
exit(0);
}
I would assume the desired solution is to actually implement the algorithmn. Then, since your're decrypting yourself, you can bail early, which, assuming the plain text is also A-Za-z0-9, gives you a 98% chance of being able to stop after decrypting a single byte, a 99.97% chance of stoping after decrypting 2 bytes, and a 99.9995% chance of stopping after 3 bytes.
Also, use C or Ocaml or something like that. You're probably spending MUCH more time doing string manipulation than you are doing cryption. Or, at least use multi-processing and spin up all your cores...
There is an obvious factor 256 speedup: One bit per byte isn't part of the key. DES has only a 56 bit key, but one passes in 64 bits. Figure out which bit it is, and throw away equivalent characters.
I've had quite a bit of help and this is a solution in C. As I am a C beginner, it's probably full of bugs and bad practice, but it works.
As CodeInChaos figured out, only 31 characters need to be tested, because DES ignores every 8th bit of the key, making for example ASCII characters b: *0110001*0 and c: *0110001*1 identical in encryption/decryption when used as a part of the key.
I am using the OpenSSL library for DES decryption. On my machine the speed it achieves is ~1.8 million passwords per second, which puts the total time to test the entire key space to around 5 days. This falls a day short of the deadline. A lot better than the Python code above which is in the years territory.
There is still room for improvement, probably the code could be optimized and threaded. If I could use all my cores I estimate the time would go down to a bit more than a day, however I have no experience with threading yet.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <openssl/des.h>
static long long unsigned nrkeys = 0; // performance counter
char *
Encrypt( char *Key, char *Msg, int size)
{
static char* Res;
free(Res);
int n=0;
DES_cblock Key2;
DES_key_schedule schedule;
Res = ( char * ) malloc( size );
/* Prepare the key for use with DES_ecb_encrypt */
memcpy( Key2, Key,8);
DES_set_odd_parity( &Key2 );
DES_set_key_checked( &Key2, &schedule );
/* Encryption occurs here */
DES_ecb_encrypt( ( unsigned char (*) [8] ) Msg, ( unsigned char (*) [8] ) Res,
&schedule, DES_ENCRYPT );
return (Res);
}
char *
Decrypt( char *Key, char *Msg, int size)
{
static char* Res;
free(Res);
int n=0;
DES_cblock Key2;
DES_key_schedule schedule;
Res = ( char * ) malloc( size );
/* Prepare the key for use with DES_ecb_encrypt */
memcpy( Key2, Key,8);
DES_set_odd_parity( &Key2 );
DES_set_key_checked( &Key2, &schedule );
/* Decryption occurs here */
DES_ecb_encrypt( ( unsigned char (*) [8]) Msg, ( unsigned char (*) [8]) Res,
&schedule, DES_DECRYPT );
return (Res);
}
void ex_program(int sig);
int main()
{
(void) signal(SIGINT, ex_program);
FILE *f, *g; // file handlers
int counter, i, len = 8; // counters and password length
char cbuff[8], mbuff[8]; // buffers
char letters[] = "02468ACEGIKMOQSUWYacegikmoqsuwy"; // reduced letter pool for password brute force
int nbletters = sizeof(letters)-1;
int entry[len];
char *password, *decrypted;
// read first 8 bytes of the encrypted file
f = fopen("test2.dat", "rb");
if(!f) {
printf("Unable to open the file\n");
return 1;
}
for (counter = 0; counter < 8; counter ++) cbuff[counter] = fgetc(f);
fclose(f);
// read first 8 bytes of the plaintext file
g = fopen("test2.txt", "r");
if(!f) {
printf("Unable to open the file\n");
return 1;
}
for (counter = 0; counter < 8; counter ++) mbuff[counter] = fgetc(g);
fclose(g);
// fill the initial key
for(i=0 ; i<len ; i++) entry[i] = 0;
// loop until the length is reached
do {
password = malloc(8);
decrypted = malloc(8);
// build the pasword
for(i=0 ; i<len ; i++) password[i] = letters[entry[i]];
nrkeys++;
if(nrkeys % 10000000 == 0) {
printf("Current key: %s\n", password);
}
// decrypt
memcpy(decrypted,Decrypt(password,cbuff,8), 8);
// compare the decrypted with the mbuff
// if they are equal, exit the loop, we have the password
if (strcmp(mbuff, decrypted) == 0)
{
printf("We've got it! The key is: %s\n", password);
printf("%lld keys searched", nrkeys);
exit(0);
}
free(password);
free(decrypted);
// spin up key until it overflows
for(i=0 ; i<len && ++entry[i] == nbletters; i++) entry[i] = 0;
} while(i<len);
return 0;
}
void ex_program(int sig) {
printf("\n\nProgram terminated %lld keys searched.\n", nrkeys);
(void) signal(SIGINT, SIG_DFL);
exit(0);
}
I can't help but notice the wording of the assignment: you are not actually requested to provide a DES implementation or cracker yourself. If that is indeed the case, why don't you take a look at tools such as John the Ripper or hashcat.
This answer may be complementary to other more specific suggestions but the first thing you should do is run a profiler.
There are really nice examples here:
How can you profile a python script?
EDIT:
For this particular task, I realize it will not help. A trial frequency of 10 GHz is... Hard on a single machine with frequency less than that. Perhaps you could mention what hardware you have available.
Also, don't aim for running it during a few hours. When you find a method that gives a reasonable probability of success within the week you have then let it run while improving your methods.
Related
I made these different programs in different programming languages to count the number of lines of a file, and it turns out that the output differs according to the program, but the strange thing is that some programs have the same results, I was testing them with a 6gb utf-8 xml file with about 146 million lines.
# Python
# Output -> 146114085 lines
import time
lines = 0
start = time.perf_counter()
with open('file_path') as myfile:
for line in myfile:
lines += 1
print("{} lines".format(lines))
end = time.perf_counter()
elapsed = end - start
print(f'Elapsed time: {elapsed:.3f} seconds')
// Java
// Output -> 146114085 lines (just as with python)
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
long startTime = System.currentTimeMillis();
int BUFFER_SIZE = 1024*1024;
String filePath = "file_path";
FileReader file = file = new FileReader(filePath);
BufferedReader reader = new BufferedReader(file, BUFFER_SIZE);
long lines = reader.lines().count();
reader.close();
System.out.println("The number of lines is " + lines);
long elapsedTime = System.currentTimeMillis() - startTime;
System.out.println("Duration in seconds: " + elapsedTime/1000);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
// Rust
// Output -> 146113746 lines
use std::fs::File;
use std::io::{BufRead, BufReader, Error, Read};
use std::time::Instant;
fn main() {
let file_path = "file_path";
let buffer_size = 1024*1024;
let start = Instant::now();
if let Err(err) = read_file(buffer_size, file_path) {
println!("{}", err);
}
let duration = start.elapsed();
println!("The function took {} seconds to execute", duration.as_secs());
}
fn read_file(buffer_size: usize, file_path: &str) -> Result<(), Error> {
let file = File::open(file_path)?;
let reader = BufReader::with_capacity(buffer_size, file);
let lines = reader.lines().fold(0, |sum, _| sum + 1);
println!("Number of lines {}", lines);
Ok(())
}
// C
// Output -> 146113745 lines (one line less than rust output)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[]) {
// start time
clock_t start = clock();
// File path
const char* file_path = "file_path";
// Open the file for reading
FILE *fp = fopen(file_path, "r");
// Allocate a buffer to hold the data
const size_t BUFFER_SIZE = 1024*1024;
char *buffer = malloc(BUFFER_SIZE);
// Declare the number of lines variable
unsigned int lines = 0;
// Read the data in chunks
while (!feof(fp)) {
// Read a chunk of data from the file
size_t bytes_read = fread(buffer, 1, BUFFER_SIZE, fp);
// Process the data here...
for (int i = 0; i < bytes_read; i++) {
if (buffer[i] == '\n') {
lines++;
}
}
}
printf("The number of lines %u\n", lines);
// Clean up
free(buffer);
fclose(fp);
// End
clock_t end = clock();
// Calculate the elapsed time in seconds
double elapsed = (double) ((end - start) / CLOCKS_PER_SEC);
printf("Elapsed time: %f seconds", elapsed);
return 0;
}
Finally, the command wc
Output -> 146113745 lines (just as with C)
wc -l file_path
I think the correct answer is Rust's, because it has one more than wc/C, and it is the last line that has no line change as it reaches the end of the file. The cases that cause me confusion are java and python.
My Regex expression for a line is .*?\\n|.+. This works in https://regexr.com/.
For some reason in the file reading implementation I'm using in Python and Java the character '\r' is interpreted as a line feed, but this doesn't happen with the Rust implementation, nor the wc one and obviously neither with the one I made in C (even when it is explicit).
But if I change the conditional ((buffer[i] == '\n') for ((buffer[i] == '\n') || (buffer[i] == '\r')) I get the same value as in Python and Java minus 1.
I created a kernel module and I want to communicate using a /proc file between the module and a script in python.
I am using the Ubuntu 22.04 kernel version v5.15. I tried to create the /proc file in my module below:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h> // kmalloc()
#include <linux/uaccess.h> // copy_to/from_user()
#include <linux/proc_fs.h>
static struct proc_dir_entry *parent;
char etx_array[] = "hello how are you?";
int len = sizeof(etx_array) / sizeof(char);
static int open_proc(struct inode *inode, struct file *file)
{
pr_info("proc file opend.....\t");
return 0;
}
/*
* This function will be called when we close the procfs file
*/
static int release_proc(struct inode *inode, struct file *file)
{
pr_info("proc file released.....\n");
return 0;
}
/*
* This function will be called when we read the procfs file
*/
static ssize_t read_proc(struct file *filp, char __user *buffer, size_t length, loff_t * offset)
{
pr_info("proc file read.....\n");
if (copy_to_user(buffer, etx_array, len))
pr_err("Data Send : Err!\n");
return length;;
}
/*
* This function will be called when we write the procfs file
*/
static ssize_t write_proc(struct file *filp, const char *buff, size_t len, loff_t * off)
{
pr_info("proc file wrote.....\n");
if (copy_from_user(etx_array, buff, len))
pr_err("Data Write : Err!\n");
return len;
}
static struct proc_ops proc_fops = {
.proc_open = open_proc,
.proc_read = read_proc,
.proc_write = write_proc,
.proc_release = release_proc,
};
static int etx_driver_init(void)
{
proc_create("etx_proc", 0666, parent, &proc_fops);
return 0;
}
static void etx_driver_exit(void)
{
proc_remove(parent);
}
module_init(etx_driver_init);
module_exit(etx_driver_exit);
MODULE_LICENSE("GPL");
And if I try to use /proc file by python3 in user space like this:
import os
pf = open("/proc/etx_proc","r")
print(pf.read())
So I get this (running the python program):
The problem here is that pf.read() in Python reads the entire file. How does the kernel know when the content of your proc file is over? When you return 0 from your .proc_read function. Since you are always copying etx_array out and you are always returning length, this means that to any application that tries to read the file (and also to the kernel itself) it will look like the file has infinite length. Python will keep reading and reading until it eventually runs out of memory and gets killed by the kernel OOM killer (or until your system freezes).
Always returning the requested size (length) is wrong as it does not match the actual length of the data copied to userspace. You have to check the requested size, copy no more than that and also no more than your buffer size (len), then return a meaningful value. You can keep track of how much you read with the loff_t * pointer that gets passed to your functions.
The same reasoning goes for your .proc_write function: it doesn't make sense to always return len. Check the requested size, cap it as needed, then perform the operation and return a meaningful value.
Copying data to/from userspace is a lot trickier than you might think, and there are a lot of pitfalls, you need to check everything that could possibly go wrong, specially when dealing with sizes. Here's an example of how this would work:
// Side note: this is the correct "len" you want.
size_t len = sizeof(etx_array) / sizeof(char) - 1;
// ...
static ssize_t read_proc(struct file *filp, char __user *buf, size_t size, loff_t *off)
{
loff_t offset = *off;
size_t remaining;
pr_info("proc file read\n");
if (offset < 0)
return -EINVAL;
if (offset >= len || size == 0)
return 0;
if (size > len - offset)
size = len - offset;
remaining = copy_to_user(buf, etx_array + offset, size);
if (remaining == size) {
pr_err("copy_to_user failed\n");
return -EFAULT;
}
size -= remaining;
*off = offset + size;
return size;
}
static ssize_t write_proc(struct file *filp, const char *buf, size_t size, loff_t *off)
{
loff_t offset = *off;
size_t remaining;
pr_info("proc file write\n");
if (offset < 0)
return -EINVAL;
if (offset >= len || size == 0)
return 0;
if (size > len - offset)
size = len - offset;
remaining = copy_from_user(etx_array + offset, buf, size);
if (remaining == size) {
pr_err("copy_from_user failed\n");
return -EFAULT;
}
size -= remaining;
*off = offset + size;
return size;
}
Check out this other answer of mine talking about simple_read_from_buffer() / simple_write_to_buffer(), which are simpler kernel interfaces that accomplish exactly the same as the above code for you automatically and (most importantly) correctly.
i use an MCP9600 sensor to know the temperature. I use an ATmega 2560 and i communicate from my laptop with python with the library serial.
this is my arduino
#include <Wire.h>
#include <Adafruit_I2CDevice.h>
#include <Adafruit_I2CRegister.h>
#include "Adafruit_MCP9600.h"
#include <SimpleCLI.h>
#define I2C_ADDRESS (0x67)
Adafruit_MCP9600 mcp;
uint8_t filtcoeff;
// Create CLI Object
SimpleCLI cli;
// Commands
Command type;
Command filter;
Command temp;
Command fanspeed;
Command Tmax;
Command tolerance;
//Call function
void overheat();
void deltatemp();
// Callback function
void typeCallback();
void filterCallback();
void temperatureCallback();
void FanCallback();
void overheatCallback();
void toleranceCallback();
int broche_PWM = 2; // Déclaration de la Pin 10 Arduino
int Valeur_PWM = 128; // Variable
int timedelay = 300;
int tempTolerance = 10;
int tempmax = 50;
void setup() {
// put your setup code here, to run once:
pinMode(broche_PWM, OUTPUT); // Pin 2 Arduino en sortie PWM
Serial.begin(115200);
while (!Serial) {
delay(10);
}
cli.setOnError(errorCallback); // Set error Callback
/* Initialise the driver with I2C_ADDRESS and the default I2C bus. */
if (! mcp.begin(I2C_ADDRESS)) {
Serial.println("Sensor not found. Check wiring!");
while (1);
}
mcp.setADCresolution(MCP9600_ADCRESOLUTION_12);
switch (mcp.getADCresolution()) {
case MCP9600_ADCRESOLUTION_18: ; break;
case MCP9600_ADCRESOLUTION_16: ; break;
case MCP9600_ADCRESOLUTION_14: ; break;
case MCP9600_ADCRESOLUTION_12: ; break;
}
mcp.setThermocoupleType(MCP9600_TYPE_K);
switch (mcp.getThermocoupleType()) {
case MCP9600_TYPE_K: ; break;
case MCP9600_TYPE_J: ; break;
case MCP9600_TYPE_T: ; break;
case MCP9600_TYPE_N: ; break;
case MCP9600_TYPE_S: ; break;
case MCP9600_TYPE_E: ; break;
case MCP9600_TYPE_B: ; break;
case MCP9600_TYPE_R: ; break;
}
mcp.setFilterCoefficient(3);
mcp.setAlertTemperature(1, 30);
mcp.configureAlert(1, true, true); // alert 1 enabled, rising temp
mcp.enable(true);
type = cli.addBoundlessCommand("type", typeCallback);
filter = cli.addBoundlessCommand("filter", filterCallback);
temp = cli.addBoundlessCommand("temp", temperatureCallback);
fanspeed = cli.addBoundlessCommand("fanspeed", FanCallback);
Tmax = cli.addBoundlessCommand("Tmax", overheatCallback);
tolerance = cli.addBoundlessCommand("Tolerance", toleranceCallback);
Serial.println("I am ready"); // avoid to have a void monitor (avoiding blocking in python code)
}
void loop() {
// put your main code here, to run repeatedly:
// Check if user typed something into the serial monitor
if (Serial.available()) {
// Read out string from the serial monitor
String input = Serial.readStringUntil('\n');
// Parse the user input into the CLI
cli.parse(input);
}
if (cli.errored()) {
CommandError cmdError = cli.getError();
Serial.print("ERROR: ");
Serial.println(cmdError.toString());
if (cmdError.hasCommand()) {
Serial.print("Did you mean \"");
Serial.print(cmdError.getCommand().toString());
Serial.println("\"?");
}
}
if (mcp.readThermocouple() > tempmax){
overheat();
}
if (abs(mcp.readThermocouple()-mcp.readAmbient())> tempTolerance){
//deltatemp();
}
analogWrite(broche_PWM,Valeur_PWM); // Envoi du signal PWM sur la sortie numérique 10
delay(timedelay);
}
void temperatureCallback(cmd* c){
Command cmd(c); // Create wrapper object
Serial.print("Hot Junction: ");
Serial.print("x");
Serial.print(mcp.readThermocouple());
Serial.print("x");
Serial.print("Cold Junction: ");
Serial.print("x");
Serial.print(mcp.readAmbient());
Serial.print("x");
Serial.print("ADC (uV): ");
Serial.print("x");
Serial.println(mcp.readADC() * 2);
}
void filterCallback(cmd* c){
Command cmd(c); // Create wrapper object
Argument arg;
String argValue = "";
int i=0;
int IntValue;
arg = cmd.getArg(i);
argValue = arg.getValue();
IntValue = argValue.toInt();
mcp.setFilterCoefficient(IntValue);
Serial.print("Filter coefficient value set to: ");
Serial.println(mcp.getFilterCoefficient());
}
}
and the python code, i use to extract the data from the ATmega
import numpy as np
import serial
import time
def get_temperature(serial_port):
phrase = b'temp'
# print("str.encode(phrase)",str.encode(phrase))
serial_port.write(phrase)
exitloop = 0
while exitloop == 0:
if serial_port.inWaiting() > 0:
arduino_data = serial_port.readline()
print(arduino_data)
serial_port.flushOutput()
exitloop = 1
serial_port.flushOutput()
serial_port.flushInput()
return arduino_data
the thermocouple is a K type. the problem is that the value coming from the sensor give constant during a long time when i see from the arduino serial monitor and from my python code. Normally, the value must change constantly when i compare with another device but give the same value a long time like 5 min.
Someone can give a solution?
I found the problem. It comes from the ADC_resolution, i gave back at 18.
Thanks
I am mapping integers to memory in C++ (Process 1) and trying to read them in Python (Process 2) ..
Current Results:
1) map integer 3 in C++ ==> Python (b'\x03\x00\x00\x00')
2) map integer 4 in C++ ==> Python (b'\x04\x00\x00\x00'), and so on ..
code:
Process 1
#include <windows.h>
#include <iostream>
using namespace std;
void main()
{
auto name = "new";
auto size = 4;
HANDLE hSharedMemory = CreateFileMapping(NULL, NULL, PAGE_READWRITE, NULL, size, name);
auto pMemory = (int*)MapViewOfFile(hSharedMemory, FILE_MAP_ALL_ACCESS, NULL, NULL, size);
for (int i = 0; i < 10; i++)
{
* pMemory = i;
cout << i << endl;
Sleep(1000);
}
UnmapViewOfFile(pMemory);
CloseHandle(hSharedMemory);
}
Process 2
import time
import mmap
bufSize = 4
FILENAME = 'new'
for i in range(10):
data = mmap.mmap(0, bufSize, tagname=FILENAME, access=mmap.ACCESS_READ)
dataRead = data.read(bufSize)
print(dataRead)
time.sleep(1)
However, my goal is to map an array that is 320*240 in size but when I try a simple array as below
int arr[4] = {1,2,3,4};
and attempt to map to memory by * pMemory = arr;
I am getting the error "a value of type int* cannot be assigned to an entity of type int" and error code "0x80070002" ..
Any ideas on how to solve this problem??
P.S for some reason integer 9 is mapped as b'\t\x00\x00\x00' in python ==> what am I missing?
Use memcpy to copy the array to shared memory.
#include <cstring>
#include <windows.h>
int main() {
int array[320*240];
const int size = sizeof(array);
const char *name = "new";
HANDLE hSharedMemory = CreateFileMapping(NULL, NULL, PAGE_READWRITE, NULL, size, name);
void *pMemory = MapViewOfFile(hSharedMemory, FILE_MAP_ALL_ACCESS, NULL, NULL, size);
std::memcpy(pMemory, array, size);
UnmapViewOfFile(pMemory);
CloseHandle(hSharedMemory);
}
I have a C function which can read/write perfectly into the hardware register by opening the device descriptor (nf10). I am trying to do the same using Python. I am able to read the registers, but I am not able to write registers. Why am I unable to write? Is there a better way to do read/write for registers in hardware?
Relevant Python code:
#! /usr/bin/env python
import os
from fcntl import *
from struct import *
SIOCDEVPRIVATE = 35312
NF10_IOCTL_CMD_READ_STAT = SIOCDEVPRIVATE + 0
NF10_IOCTL_CMD_WRITE_REG = SIOCDEVPRIVATE + 1
NF10_IOCTL_CMD_READ_REG = SIOCDEVPRIVATE + 2
def rdaxi(addr):
f = open("/dev/nf10", "r+")
arg = pack("q", int(addr, 16))
value = ioctl(f, NF10_IOCTL_CMD_READ_REG, arg)
value = unpack("q", value)
value = value[0]
value = hex(value & int("0xffffffff", 16))
f.close()
return value
def wraxi(addr, value):
f = open("/dev/nf10", "r+")
arg = (int(addr, 16) << 32) + int(value, 16)
arg = pack("q", arg)
ioctl(f, NF10_IOCTL_CMD_WRITE_REG, arg)
f.close()
relevant C code
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define NF10_IOCTL_CMD_READ_STAT (SIOCDEVPRIVATE+0)
#define NF10_IOCTL_CMD_WRITE_REG (SIOCDEVPRIVATE+1)
#define NF10_IOCTL_CMD_READ_REG (SIOCDEVPRIVATE+2)
int main(int argc, char* argv[]){
int f;
uint64_t v;
uint64_t addr;
uint64_t val;
if(argc < 3){
printf("usage: rdaxi reg_addr(in hex) reg_val(in_hex)\n\n");
return 0;
}
else{
sscanf(argv[1], "%llx", &addr);
sscanf(argv[2], "%llx", &val);
}
//----------------------------------------------------
//-- open nf10 file descriptor for all the fun stuff
//----------------------------------------------------
f = open("/dev/nf10", O_RDWR);
if(f < 0){
perror("/dev/nf10");
return 0;
}
printf("\n");
// High 32 bits are the AXI address,
// low 32 bits are the value written to that address
v = (addr << 32) + val;
if(ioctl(f, NF10_IOCTL_CMD_WRITE_REG, v) < 0){
perror("nf10 ioctl failed");
return 0;
}
printf("\n");
close(f);
return 0;
}
I think it's best to implement lower-level operations on registers in C, and compile C to .so. Then load the .so in python.
I suspect "endianness" may be your issue. It's hard to tell without knowing the hardware you're writing to, though. I noticed you've left off the byte order specifier from your pack function call. Most hardware registers are big-endian, meaning they expect bit 0 at the lowest memory address and the most significant bit at the highest address.
Without the byte order specifier, Python will pack with your native endianness, which is little-endian on an Intel system. Try packing it with the big-endian specifier so that everything stays in the same order as it started:
arg = pack(">q", arg)