I am trying to write a library that reads 5 variables, then sends them through the serial port to a bluetooth reciever, I am getting a number of errors and I am not sure where to go from here, do I need to implement pointers?
Here is the Arduino code....
#include <serialComms.h>
serialComms testing;
void setup()
{
Serial.begin(9600);
}
char data[] = {1,2,3,4,5,6};
void loop()
{
for(int t = 0;t<6;t++)
{
data[t] = data[t]++;
}
testing.updateUser(data);
delay(250);
}
serialComms.cpp
#include <Arduino.h>
#include <serialComms.h>
void serialComms::init()
{
// This is where the constructor would be...right now we are too stupid to have one
}
void serialComms::readAllBytes() // Target Pin,Values
{
}
void serialComms::assignBytes()
{
for(int t = 0;t<5;t++)
{
digitalWrite(12,HIGH);
delay(250);
digitalWrite(12,LOW);
}
}
void serialComms::updateUser(char t[])
{
Serial.write(t,5);
}
serialComms.h
#ifndef serialComms_h
#define serialComms_h
/* serialComms Class */
class serialComms
{
public:
serialComms() {};
void init();
void readAllBytes(); // Will be used to create the array --> two variables for now...
void assignBytes();
void updateUser(char t[]);
};
#endif
Here are the errors that I am getting...
- serialComms.cpp:28: error: initializing argument 1 of 'virtual size_t Print::write(const uint8_t*, size_t)'
-
- serialComms.cpp:28: error: invalid conversion from 'char*' to 'const uint8_t*'
- serialComms.cpp: In member function 'void serialComms::updateUser(char*)':
- serialComms.cpp:27: error: expected primary-expression before ']' token
Example:
void setup()
{
Serial.begin(9600);
char string_array[] = "hello";
char data_array[] = {1,2,3,4,5,6};
unsigned char data_array_uchar[] = {21,22,23,24,25,26};
uint8_t uint8_array[] = {11,12,13,14,15,16};
char alpha_array[] = {0x41,0x42,0x43,0x44,0x45,0x46};
// take note that sizeof() is a precompile command... number of places/size of each place.
updateUserPrint(string_array);
updateUserWrite(data_array, sizeof(string_array));
updateUserWriteUchar(data_array_uchar, sizeof(data_array_uchar));
updateUserWriteUchar(uint8_array, sizeof(uint8_array));
updateUserWriteUint(uint8_array, sizeof(string_array));
updateUserAlpha(alpha_array, sizeof(string_array));
}
void updateUserPrint(char *s)
{ //note a string aka array of char's is ended with a null.
Serial.print(s); // this can detect.
Serial.println();
}
void updateUserWrite(char *t, size_t len)
{ //note an array of int's is not ended with a null. so you need to know how long it is.
for (int n = 0; n < len ; n++) {
Serial.print(t[n],DEC);
Serial.print(",");
}
Serial.println();
}
void updateUserWriteUchar(unsigned char *t, size_t len)
{ //note an array of int's is not ended with a null. so you need to know how long it is.
for (int n = 0; n < len ; n++) {
Serial.print(t[n],DEC);
Serial.print(",");
}
Serial.println();
}
void updateUserWriteUint(uint8_t *t, size_t len)
{ //note an array of int's is not ended with a null. so you need to know how long it is.
for (int n = 0; n < len ; n++) {
Serial.print(t[n],DEC);
Serial.print(",");
}
Serial.println();
}
void updateUserAlpha(char *t, int len)
{ //note an array of int's is not ended with a null. so you need to know how long it is.
for (int n = 0; n < len ; n++) {
Serial.write(t[n]);
}
Serial.println();
}
produces the following:
hello
1,2,3,4,5,6,
21,22,23,24,25,26,
11,12,13,14,15,16,
11,12,13,14,15,16,
ABCDEF
Serial.write can only send constant strings like
Serial.write(“hello”);
That is why the error error: invalid conversion from 'char*' to 'const uint8_t*'
use as
char temp[max_length];
sprintf(temp,"%s",t);
Serial.write(temp);
Related
void setup() {
Serial.begin(9600);
printArr([64,67]);
}
void loop() {}
void printArr(byte nilai[]) {
for (byte c = 0; c < length(nilai); c++) {
Serial.println(nilai[c]);
}
}
I expect the program print char of number 64 and 67 in ASCII since it was iterated in array, but instead the compiler give me error
C:\Users\User\Documents\Arduino\sketch_apr18a\sketch_apr18a.ino:10:24: note: suggested alternative: 'long'
for (byte c = 0; c < length(nilai); c++) {
^~~~~~
long
exit status 1
expected identifier before numeric constant
A solving can be:
void setup() {
Serial.begin(9600);
byte arr [] = {64,67};
printArr(arr, 2);
}
void loop() {}
void printArr(byte *nylai, unsigned d) {
for (byte c = 0; c < d; c++) {
Serial.println(*(nylai + c * sizeof(byte)));
}
}
I have this code but is not working , it keep giving me the following errors :
[Error] cannot convert 'float' to 'float*' for argument '1' to 'void zeroCrossing(float*, float*, int)'
[Error] cannot convert 'float*' to 'float' for argument '1' to 'bool getSign(float)'
[Error] cannot convert 'float*' to 'float' for argument '1' to 'bool getSign(float)'
[Error] invalid conversion from 'int' to 'float*' [-fpermissive]
#include <iostream>
#include <cstring>
using namespace std;
void zeroCrossing(float *data, float *zerCross, int nx);
bool getSign(float data);
float array[9] = {1,2,3,0,-1,-2,-3,0,1};
float *p = array;
float f1[9];
float *p2 = f1;
int bx= 2 ;
int main() {
zeroCrossing(*p,*p2,bx);
return 0 ;
}
/* zero crossing function */
/* data = input array */
/* zerCross = output zero crossing array */
void zeroCrossing(float *data[], float *zerCross[], int nx)
{
int i;
bool sign1, sign2;
memset(zerCross, 0, nx*sizeof(float));//copies the 0 to the first characters of the string
//pointed to, by argument
for(i=0; i<nx-1; i++) /* loop over data */
{
sign1 = getSign(data[i]);
sign2 = getSign(data[i+1]);
if(sign1!=sign2) /* set zero crossing location */
zerCross[i+1] = 1;
}
}
/* get sign of number */
bool getSign(float data)
{
if(data>0) /* positif data */
return (1);
else /* negatif data */
return (0);
}
When you do coding, you should compile the code after some lines of codes, unless you are pro.
There are two things I could say about your codes
Function declaration: void zeroCrossing(float *data, float *zerCross, int nx); and void zeroCrossing(float *data[], float *zerCross[], int nx) are not the same.
Variable name: Should avoid names like array because they are used in the standard lib.
This is my fix to make your code compilable
#include <iostream>
#include <cstring>
using namespace std;
void zeroCrossing(float *data, float *zerCross, int nx);
bool getSign(float data);
float array_[9] = {1,2,3,0,-1,-2,-3,0,1};
float* p = array_;
float f1[9];
float *p2 = f1;
int bx= 2 ;
/* get sign of number */
bool getSign(float data)
{
if(data>0) /* positif data */
return (1);
else /* negatif data */
return (0);
}
/* zero crossing function */
/* data = input array */
/* zerCross = output zero crossing array */
void zeroCrossing(float *data, float *zerCross, int nx)
{
int i;
bool sign1, sign2;
memset(zerCross, 0, nx*sizeof(float));//copies the 0 to the first characters of the string
//pointed to, by argument
for(i=0; i<nx-1; i++) /* loop over data */
{
sign1 = getSign(data[i]);
sign2 = getSign(data[i+1]);
if(sign1!=sign2) /* set zero crossing location */
zerCross[i+1] = 1;
}
}
int main() {
zeroCrossing(p,p2,bx);
return 0 ;
}
1 - you should minimize the number of global variables, in your case it is 0.
2 - *p points to a value stored in an address p, so in main function when you are calling zeroCrossing you need to pass an address, not value.
To be honest, I don't understand what you are trying to do but at least this code don't throw errors:
#include <iostream>
#include <cstring>
using namespace std;
void zeroCrossing(float *data, float *zerCross, int nx);
bool getSign(float data);
int main()
{
float array[9] = {1,2,3,0,-1,-2,-3,0,1};
float *p = array;
float f1[9];
float *p2 = f1;
int bx = 2 ;
zeroCrossing(p, p2, bx);
return 0 ;
}
/* zero crossing function */
/* data = input array */
/* zerCross = output zero crossing array */
void zeroCrossing(float *data, float *zerCross, int nx)
{
int i;
bool sign1, sign2;
memset(zerCross, 0, nx*sizeof(float));//copies the 0 to the first characters of the string
//pointed to, by argument
for(i=0; i<nx-1; i++) { /* loop over data */
sign1 = getSign(data[i]);
sign2 = getSign(data[i+1]);
if(sign1!=sign2) /* set zero crossing location */
zerCross[i+1] = 1;
}
}
/* get sign of number */
bool getSign(float data)
{
if(data>0) /* positif data */
return (1);
else /* negatif data */
return (0);
}
I am trying to make a library for redirection of data printed to Print class. I am unfortunately stuck on error that reads
error: cannot declare variable 'diagData' to be of abstract type 'PrintToString'
note: because the following virtual functions are pure within 'PrintToString'
note: virtual size_t PrintToString::write(uint8_t)
I tried several variations of how to implement this but with no luck. (Sourced from the internet)
Links
Print class: github.com/ Print.h and Print.cpp
My code
PrintToString.h
#ifndef PRINT_TO_STRING_H
#define PRINT_TO_STRING_H
#include <Arduino.h>
class PrintToString : public Print
{
private:
String* data;
public:
PrintToString();
~PrintToString();
String* results();
void clear();
size_t write(uint8_t) = 0;
size_t write(const uint8_t* buffer, size_t size);
};
#endif
PrintToString.cpp
#include "PrintToString.h"
PrintToString::PrintToString()
{
data = new String();
}
PrintToString::~PrintToString()
{
delete data;
data = NULL;
}
String* PrintToString::results()
{
return data;
}
void PrintToString::clear()
{
delete data;
data = new String();
}
size_t PrintToString::write(const uint8_t* buffer, size_t size)
{
size_t n = 0;
while (size--)
{
if (data->concat(*buffer++))
n++;
else
break;
}
return n;
}
TestSketch.ino (I have left out content of all the constants)
#include <ESP8266WiFi.h>
#include <PrintToString.h>
const char* WIFI_SSID
const char* WIFI_PASS
const char* API_HOST
const uint16_t API_PORT
const uint16_t LOCAL_UDP_PORT
WiFiUDP UDPClint;
PrintToString diagData;
uint64_t packetNumber = 0;
void setup()
{
WiFi.begin(WIFI_SSID, WIFI_PASS);
UDPClint.begin(LOCAL_UDP_PORT);
while (WiFi.status() != WL_CONNECTED)
delay(500);
WiFi.printDiag(diagData);
sendStringPacket(diagData.result());
diagData.clear();
}
void loop()
{
delay(1000);
}
void sendStringPacket(String payload)
{
UDPClint.beginPacket(API_HOST, API_PORT);
uint64_t thisPNumber = packetNumber++;
String thisPNumberStr;
while (thisPNumber > 0)
{
uint8_t digit = thisPNumber % 10;
thisPNumberStr.concat(digit);
thisPNumber /= 10;
}
UDPClint.write(';');
for (uint64_t i = 0; i < payload.length(); i++)
UDPClint.write(payload.charAt(i));
UDPClint.endPacket();
}
This is because this class has a pure virtual function here:
size_t write(uint8_t) = 0;
A class with a pure virtual function cannot be instantiated. So method write(uint8_t) must be somehow implemented in your code.
EDIT: Consider making use of the code you used in sendStringPacket() for write(uint8_t). You may be able to redirect output without using sendStringPacket(diagData.result()); statement.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a application that is suppose to store graphic elements. I am having an issue where I cant access a variable in a structure. Here is what i have so far.
#include <crtdbg.h>
#include <string.h>
#include <stdio.h>
#include "CLib.h"
enum{ RUNNING = 1 };
struct Point
{
int x, y;
};
struct Line
{
Point start;
Point end;
};
struct GraphicElement
{
enum{ SIZE = 256 };
char name[SIZE];
CStash Lines; // a Stash of Lines
};
struct VectorGraphic
{
CStash Elements; // a Stash of GraphicElements
};
void AddGraphicElement(VectorGraphic*);
void ReportVectorGraphic(VectorGraphic*);
void CleanUpVectorGraphic(VectorGraphic*);
VectorGraphic Image;
int main()
{
char response;
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
// it's a Stash of GraphicElements initialize(&(Image.Elements),sizeof(GraphicElement));
while (RUNNING)
{
printf("\nPlease select an option:\n");
printf("1. Add a Graphic Element\n");
printf("2. List the Graphic Elements\n");
printf("q. Quit\n");
printf("CHOICE: ");
fflush(stdin);
scanf("%c", &response);
switch (response)
{
case '1':AddGraphicElement(&Image); break;
case '2':ReportVectorGraphic(&Image); break;
case 'q':CleanUpVectorGraphic(&Image); return 0;
default:printf("Please enter a valid option\n");
}
printf("\n");
}
return 0;
}
void AddGraphicElement(VectorGraphic* pImage){
int i = 0, counter = 0;
int xPointStart = 0, yPointStart = 0;
int xPointEnd = 0, yPointEnd = 0;
char name[50];
int lineNumber = 0;
GraphicElement *pElement = nullptr;
Line *pLine = nullptr;
initialize(&(Image.Elements), sizeof(GraphicElement));
printf("ADDING A Graphic Element\n");
printf("Please enter the name of the new GraphicElement(<256 characters): ");
fflush(stdin);
scanf("\n%[^\n]s", &name);
fflush(stdin);
strcpy(pElement->name,name);
Anytime I try assigning strcpy(pElement->name,name); it tells me access violation.
The two other files im working with that cannot be changed and are from a textbook called Thinking in C++.
//: C04:CLib.cpp {O}
// Implementation of example C-like library
// Declare structure and functions:
#include "CLib.h"
#include <iostream>
#include <cassert>
using namespace std;
// Quantity of elements to add
// when increasing storage:
const int increment = 100;
void initialize(CStash* s, int sz)
{
s->size = sz;
s->quantity = 0;
s->storage = nullptr;
s->next = 0;
}
int add(CStash* s, const void* element)
{
if (s->next >= s->quantity) //Enough space left?
inflate(s, increment);
// Copy element into storage,
// starting at next empty space:
int startBytes = s->next * s->size;
unsigned char* e = (unsigned char*)element;
for (int i = 0; i < s->size; i++)
s->storage[startBytes + i] = e[i];
s->next++;
return(s->next - 1); // Index number
}
void* fetch(CStash* s, int index)
{
// Check index boundaries:
assert(0 <= index);
if (index >= s->next)
return 0; // To indicate the end
// Produce pointer to desired element:
return &(s->storage[index * s->size]);
}
int count(CStash* s)
{
return s->next; // Elements in CStash
}
void inflate(CStash* s, int increase)
{
assert(increase > 0);
int newQuantity = s->quantity + increase;
int newBytes = newQuantity * s->size;
int oldBytes = s->quantity * s->size;
unsigned char* b = new unsigned char[newBytes];
for (int i = 0; i < oldBytes; i++)
b[i] = s->storage[i]; // Copy old to new
delete[](s->storage); // Old storage
s->storage = b; // Point to new memory
s->quantity = newQuantity;
}
void cleanup(CStash* s)
{
if (s->storage != 0)
{
cout << "freeing storage" << endl;
delete[]s->storage;
}
} ///:~
and the .h file...
//: C04:CLib.h
// Header file for a C-like library
// An array-like entity created at runtime
typedef struct CStashTag {
int size; // Size of each space
int quantity; // Number of storage spaces
int next; // Next empty space
unsigned char* storage;// Dynamically allocated array of bytes
} CStash;
void initialize(CStash* s, int size);
void cleanup(CStash* s);
int add(CStash* s, const void* element);
void* fetch(CStash* s, int index);
int count(CStash* s);
void inflate(CStash* s, int increase);
///:~
GraphicElement *pElement = nullptr;
// ...
strcpy(pElement->name,name);
Somewhere between the top line and bottom line above you need to allocate memory for pElement.
pElement = new GraphicElement();
Also, consider using a std::shared_ptr instead of a raw pointer, given you tagged this C++.
In my code, I have a statically allocated array in global memory (i.e., allocated using __device__), which I want to sort using thrust::sort, which isn't working. All of the examples on this topic are using CUDA runtime allocated arrays (using cudaMalloc). Is there any way I can sort a statically allocated array?
I guess it has something to do with statically allocated memory not being accessible from the host. Using cudaMalloc-allocated arrays, it is working fine. However, I want to avoid using this type of allocation since static allocation allows for easier access to the data from device code (doesn't it?).
Minimal (not-) working example:
#include <stdio.h>
#include <thrust/device_ptr.h>
#include <thrust/sort.h>
#define N 4
typedef struct element {
int key;
int value;
__host__ __device__ bool operator<(element e) const
{ return key > e.key; }
} element;
__device__ element array[N];
__global__ void init() {
for (int i = 0; i < N; ++i) {
array[N - i - 1].key = i;
}
}
__global__ void print_array() {
for (int i = 0; i < N; ++i) {
printf("%d ", array[i].key);
}
printf("\n");
}
int main(void) {
thrust::device_ptr<element> array_first(array);
init<<<1,1>>>();
printf("unsorted: ");
print_array<<<1, 1>>>();
cudaDeviceSynchronize();
thrust::sort(array_first, array_first + N);
printf("sorted: ");
print_array<<<1, 1>>>();
cudaDeviceSynchronize();
}
Use cudaGetSymbolAddress to take the address of the array variable from a __host__ function:
void* array_ptr = 0;
cudaGetSymbolAddress(&array_ptr, array);
thrust::device_ptr<element> array_first(reinterpret_cast<element*>(array_ptr));
Here's the complete program:
#include <stdio.h>
#include <thrust/device_ptr.h>
#include <thrust/sort.h>
#define N 4
typedef struct element {
int key;
int value;
__host__ __device__ bool operator<(element e) const
{ return key > e.key; }
} element;
__device__ element array[N];
__global__ void init() {
for (int i = 0; i < N; ++i) {
array[N - i - 1].key = i;
}
}
__global__ void print_array() {
for (int i = 0; i < N; ++i) {
printf("%d ", array[i].key);
}
printf("\n");
}
int main(void) {
cudaError_t error;
void* array_ptr = 0;
if(error = cudaGetSymbolAddress(&array_ptr, array))
{
throw thrust::system_error(error, thrust::cuda_category());
}
thrust::device_ptr<element> array_first(reinterpret_cast<element*>(array_ptr));
init<<<1,1>>>();
printf("unsorted: ");
print_array<<<1, 1>>>();
if(error = cudaDeviceSynchronize())
{
throw thrust::system_error(error, thrust::cuda_category());
}
thrust::sort(array_first, array_first + N);
if(error = cudaDeviceSynchronize())
{
throw thrust::system_error(error, thrust::cuda_category());
}
printf("sorted: ");
print_array<<<1, 1>>>();
if(error = cudaDeviceSynchronize())
{
throw thrust::system_error(error, thrust::cuda_category());
}
return 0;
}
Here's the output on my system:
$ nvcc test.cu -run
unsorted: 3 2 1 0
sorted: 3 2 1 0
The sorted output is the same as the unsorted output, but I guess that is intentional given the way the data is generated and the definition of element::operator<.
This:
__device__ element array[N];
...
thrust::device_ptr<element> array_first(array);
is illegal. In host code, array is a host address and can't be passed to device code. Do something like this instead:
element* array_d;
cudaGetSymbolAddress((void **)&array_d, array);
thrust::device_ptr<element> array_first(array_d);
i.e. you need to use cudaGetSymbolAddress to read the address from the GPU context at runtime, then you can use the result of that call in GPU code.