My question will be Arduino specific, I wrote a code that turns array of characters (text) into binary string, but the problem is that the binary representation is not 8 bits, its sometimes 7 bits, 6 bits or even 1 bit representation (if you have a value of 1 as decimal). I'm using String constructor String(letter, BIN) to store the binary representation of letter in a string.
I would like to have a 8 bits representation or even a 7 bits representation.
String text = "meet me in university";
String inbits;
byte after;
byte bits[8];
byte x;
char changed_char;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("Press anything to begin");
inbits = convertToBits(text);
}
String convertToBits(String plaintext)
{
String total,temp;
total = String(plaintext[0],BIN);
total = String(total + " ");
for (int i=1;i<plaintext.length();i++)
{
temp = String (plaintext[i],BIN);
total = String(total + temp);
total = String(total + " ");
}
Serial.println(total);
return total;
}
If the length of the argument string is less then 8, prepend "0"s until it is 8 bits long.
You could do something similar to the following:
void PrintBinary(const std::string& test)
{
for (int c = 0; c < test.length(); c++)
{
unsigned bits = (unsigned)test[c];
for (int i = 0; i < 8; i++)
{
std::cout << ((bits >> (7 - i)) & 1U);
}
std::cout << " ";
}
}
Modifying the above example to use String and Serial.println instead of std::string and std::cout should be trivial. I don't own an arduino to test with so I couldn't modify your code and test if the above is possible in the environment you work in but I assume it is.
PrintBinary("Hello"); //Output: 01001000 01100101 01101100 01101100 01101111
String(letter, BIN) doesn't zero pad the string. You have to do it yourself.
You need to prepend the 0 character until your binary string is 8 characters long.
String convertToBits(String plaintext)
{
String total, temp;
total = "";
for (int i=0; i<plaintext.length(); i++)
{
temp = String (plaintext[i], BIN);
while (temp.length() < 8)
temp = '0' + temp;
if (i > 0)
total = String(total + " ");
total = String(total + temp);
}
Serial.println(total);
return total;
}
Related
I have an arudino code where I get some temperature reading:
double c1 = device.readCelsius();
Serial.println(c1);
The output is for example: 26.23
What I need is to get this converted to 2623 and then to HEX value so I get: 0x0A3F
Any clue?
I guess your float values always get numbers up to two decimal. So, you can just multiply the value which you read from sensor with a 100.
decimalValue = 100 * c1
And then you can use this small code for converting the decimal value to HEX.
Thanks to GeeksforGeeks
You can find the full tutorial here
// C++ program to convert a decimal
// number to hexadecimal number
#include <iostream>
using namespace std;
// function to convert decimal to hexadecimal
void decToHexa(int n)
{
// char array to store hexadecimal number
char hexaDeciNum[100];
// counter for hexadecimal number array
int i = 0;
while (n != 0) {
// temporary variable to store remainder
int temp = 0;
// storing remainder in temp variable.
temp = n % 16;
// check if temp < 10
if (temp < 10) {
hexaDeciNum[i] = temp + 48;
i++;
}
else {
hexaDeciNum[i] = temp + 55;
i++;
}
n = n / 16;
}
// printing hexadecimal number array in reverse order
for (int j = i - 1; j >= 0; j--)
cout << hexaDeciNum[j];
}
// Driver program to test above function
int main()
{
int n = 2545;
decToHexa(n);
return 0;
}
So I'm doing an AT command and the reply is
AT+CGDCONT?
+CGDCONT: 1,"IP","hologram","0.0.0.0",0,0,0,0
+CGDCONT: 13,"IP","hologram","0.0.0.0",0,0,0,0
+CGDCONT: 14,"IP","hologram","0.0.0.0",0,0,0,0
OK
I need to get the numbers out of this that are written before the "IP" (for this example they are 1,13,14). The numbers range from 1-24 as do the number of lines.
I was reading the reply from the command and saving it as a String with
String input;
SerialAT.println("AT+CGDCONT?");
delay(500);
if (SerialAT.available()) {
input = SerialAT.readString();
Serial.println(input);
}
Right now I am reading the stream reply and saving it as a String. The String is then cut at the newline (\n) and stored pieces in an array. After that, I have it read the array and stop once it hits a "," which is right after the number. Then it identifies the section that contains ": " which is right before the number and gets the index position of the ": " and uses that to take a substring of what is left which is just the number.
So for the example that I have, it would put the first row into the array looking like this
+CGDCONT: 1,"IP","hologram","0.0.0.0",0,0,0,0
It would be read one char at a time until the first "," is identified like this
+
+C
+CG
+CGD
+CGDC
+CGDCO
+CGDCON
+CGDCONT
+CGDCONT:
+CGDCONT:
+CGDCONT: 1
then the position of ": " would be identified and for this example, it would be 9. So everything after the 9th position inside of the array would be the output which is 1.
This is working flawlessly and I have even sent in garbled text before the +CGDCONT: because sometimes that's what the modem replies if it didn't have time to fully process the command and it has always fed me the numbers out correctly.
My code for this is
String input;
SerialAT.println("AT+CGDCONT?");
delay(500);
if (SerialAT.available()) {
input = SerialAT.readString();
Serial.println(input);
} else {
Serial.println("Failed to get PDP!");
}
const int numberOfPieces = 10;
String pieces[numberOfPieces];
int counter = 0;
int lastIndex = 0;
for (int i = 0; i < input.length(); i++) {
if (input.substring(i, i + 1) == "\n") {
pieces[counter] = input.substring(lastIndex, i);
lastIndex = i + 1;
counter++;
}
if (i == input.length() - 1) {
pieces[counter] = input.substring(lastIndex, i);
}
}
input = "";
counter = 0;
lastIndex = 0;
String readString, data;
int D;
int PDPcounter = 0;
for ( int i = 0; i < numberOfPieces; i++) {
for ( int x = 0; x < pieces[i].length(); x++) {
char c = pieces[i][x]; //gets one byte from buffer
Serial.println(readString);
if (c == ',') {
if (readString.indexOf(": ") >= 0) {
data = readString.substring((readString.indexOf(": ") + 1));
D = data.toInt();
Serial.println(D);
PDP[PDPcounter] = D;
Serial.print("PDPcounter = "); Serial.println(PDPcounter);
PDPcounter++;
readString = "";
data = "";
break;
}
readString = "";
data = "";
}
else {
readString += c;
}
}
}
At the very end, I try and read the contents of the PDP array with
for ( int i = 0; i < 10; i++) {
Serial.print(i);
Serial.print(" - ");
Serial.println(PDP[i]);
}
and I am getting the following
0 - 1
1 - 13
2 - 14
3 - 0
4 - 0
5 - 0
6 - 0
7 - 0
8 - 0
9 - 0
which is exactly what I need.
I guess the only help that I need now is code cleanup recommendations.
I just bought a 8x32 lattice board (led matrix) and I control it with Arduino. The problem is that I can only use text with the library I got on github. But not numbers, how can I do it?
I'm going to put the code below, the code of the scrolling text and the part of the code in the library that specifies the function used to set the text.
The arduino code that program the scrolling text is here:
#include <HT1632.h>
#include <font_5x4.h>
#include <images.h>
int i = 0;
int wd;
char disp[] = "Hello, how are you?";
int x = 10;
void setup() {
HT1632.begin(A5, A4, A3);
wd = HT1632.getTextWidth(disp, FONT_5X4_END, FONT_5X4_HEIGHT);
}
void loop() {
HT1632.renderTarget(1);
HT1632.clear();
HT1632.drawText(disp, OUT_SIZE - i, 2, FONT_5X4, FONT_5X4_END,
FONT_5X4_HEIGHT);
HT1632.render();
i = (i + 1) % (wd + OUT_SIZE);
delay(100);
}
The library code that specifies the printing of the text is this:
void HT1632Class::drawText(const char text[], int x, int y, const byte font[],
int font_end[], uint8_t font_height,
uint8_t gutter_space) {
int curr_x = x;
char i = 0;
char currchar;
// Check if string is within y-bounds
if (y + font_height < 0 || y >= COM_SIZE)
return;
while (true) {
if (text[i] == '\0')
return;
currchar = text[i] - 32;
if (currchar >= 65 &&
currchar <=
90) // If character is lower-case, automatically make it upper-case
currchar -= 32; // Make this character uppercase.
if (currchar < 0 || currchar >= 64) { // If out of bounds, skip
++i;
continue; // Skip this character.
}
// Check to see if character is not too far right.
if (curr_x >= OUT_SIZE)
break; // Stop rendering - all other characters are no longer within the
// screen
// Check to see if character is not too far left.
int chr_width = getCharWidth(font_end, font_height, currchar);
if (curr_x + chr_width + gutter_space >= 0) {
drawImage(font, chr_width, font_height, curr_x, y,
getCharOffset(font_end, currchar));
// Draw the gutter space
for (char j = 0; j < gutter_space; ++j)
drawImage(font, 1, font_height, curr_x + chr_width + j, y, 0);
}
curr_x += chr_width + gutter_space;
++i;
}
}
You need to look at snprintf. This allows you to format a string of characters just like printf. It allows you to convert something like a int into a part of a string.
an example:
int hour = 10;
int minutes = 50;
char buffer[60];
int status = snprintf(buffer, 60, "the current time is: %i:%i\n", hour, minutes);
buffer now contains:"the current time is: 10:50" (and several empty characters past the \0).
I need to implement a Rc4 algorithm with a seed: 1 2 3 6 and the plain text cryptology. I am following this guideline we were provided in class, but it's not initializing S correctly.
my output is
and needs to be
My code was previously printing negative values , not sure why but I managed to fix that error. Thought everything was good to go but it's not. Sorry for the pictures, I figured it was easier to explain what I was following for my code structure. I am mod 4 the seed since it contains 4 characters, could that possibly be my error?
#include <iostream>
#include <string>
#include <string.h>
using std::endl;
using std::string;
void swap(unsigned int *x, unsigned int *y);
int main()
{
string plaintext = "cryptology";
char cipherText[256] = { ' ' };
unsigned int S[256] = { 0 };
unsigned int t[256] = { 0 };
unsigned int seed[4] = { 1, 2, 3, 6 }; // seed used for test case 1
unsigned int temp = 0;
int runningTotal = 0;
unsigned int key = 0;
// inilializing s and t
for (int i = 0; i < 256; i++)
{
S[i] = i;
t[i] = seed[i % 4];
}
for (int i = 0; i < 256; i++)
{
runningTotal += S[i] + t[i];
runningTotal %= 256;
swap(&S[runningTotal], &S[i]);
std::cout << S[i] <<" ";
}
runningTotal = 0;
for (int i = 0; i < plaintext.size(); i++)
{
runningTotal %= 256;
swap(&S[i], &S[runningTotal]);
temp = (unsigned int)S[i] + (unsigned int)S[runningTotal];
temp %= 256;
key = S[temp];
std::cout << endl;
cipherText[i] = plaintext[i] ^ key;
}
std::cout << " this is cipher text " << endl;
std::cout << cipherText << endl;
system("pause");
return 0;
}
void swap(unsigned int *x, unsigned int *y)
{
unsigned int temp = 0;
temp = *x;
*x = *y;
*y = temp;
}
Actually I think you're generating S[] correctly. I can only assume you're supposed to do something different with the key. (Perhaps's its an ASCII string instead of four byte values? Check your assignment notes.)
There is a problem later on, however. In the stream generation loop, you're supposed to do the increment and swap operations before you fetch a byte from S[].
for (int k = 0; k < plaintext.size(); k++)
{
i = (i+1) % 256; // increment S[] index
runningTotal = (runningTotal + S[i]) % 256; // swap bytes
swap(&S[i], &S[runningTotal]);
temp = (S[i] + S[runningTotal]) % 256; // fetch byte from S and
cipherText[k] = plaintext[k] ^ S[temp]; // XOR with plaintext
}
NOTE: Although unrelated to your question, your code could be made a lot tidier by using unsigned char values instead of ints. That would eliminate the % 256 instructions that are littered all over the place. (But be careful during initialization, because i<256 will always be true if i is an unsigned char.)
I've got the following function to make a conversion from a Hex String to a Byte array. Then, I calculate the Checksum:
private String CalcChecksum (String message) {
/**Get string's bytes*/
//byte[] bytes = DatatypeConverter.parseHexBinary(message.replaceAll("\\s","")).getBytes();
message = message.replaceAll("\\s","");
byte[] bytes = hexToByteArray(message);
byte b_checksum = 0;
for (int byte_index = 0; byte_index < bytes.length; byte_index++) {
b_checksum += bytes[byte_index];
}
int d_checksum = b_checksum; //Convert byte to int(2 byte)
int c2_checksum = 256 - d_checksum; //Hacer complemento a 2
String hexString = Integer.toHexString(c2_checksum); //Convertir el entero (decimal) a hexadecimal
return hexString;
}
public static byte[] hexToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
}
return data;
}
Making some test, for example for the hex value "e0", the hexToByteArray is getting the value "-32". So the final returning value in the CalcChecksum is "17a".
What I need is to get unsigned values in the hexToByteArray function. This is because i need to send the Checksum in a hexString to a MCU where the Checksum is calculated with unsigned values, so isntead of get the "-32" value, it gets "224" and the final hex value is "7a" instead of "17a".
i think that doing some kind of conversion like when the byte result is a negative value, do something like 255 + "negative value" + 1. This will convert "-32" into "224".
The problem is that i'm trying to do it, but i'm having some errors making the conversions between bytes, int, etc...
So, how could i do?
For the moment, I think that this can be the solution.
Just including in the CalcChecksum function the next code after int d_checksum = b_checksum;:
if (d_checksum < 0) {
d_checksum = 255 + d_checksum + 1;
}